Search

Dark theme | Light theme
Showing posts with label SpringSweets:Gradle. Show all posts
Showing posts with label SpringSweets:Gradle. Show all posts

September 4, 2018

Spring Sweets: Dockerize Spring Boot Application With Jib

Jib is an open-source Java library from Google for creating Docker images for Java applications. Jib can be used as Maven or Gradle plugin in our Spring Boot project. One of the nice feature of Jib is that it adds layers with our classes, resources and dependency libraries for the Docker image. This means that when only class files have changed, the classes layer is rebuild, but the others remain the same. Therefore the creation of a Docker image with our Spring Boot application is also very fast (after the first creation). Also the Maven and Gradle plugins have sensible defaults, like using the project name and version as image name, so we don't have to configure anything in our build tool. Although Jib provides options to configure other values for the defaults, for example to change the JVM options passed on to the application.

Let's see Jib in action for a simple Spring Boot application. In our example we use Gradle as build tool with the following Spring Boot application:

// File: src/main/java/mrhaki/spring/sample/SampleApplication.java
package mrhaki.spring.sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
@SpringBootApplication
public class SampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }

    @GetMapping("/message")
    Mono<String> message() {
        return Mono.just("Spring Boot sample application.");
    }
    
}

Next we add the Jib plugin to our Gradle build file:

// File: build.gradle
...
plugins {
    id 'com.google.cloud.tools.jib' version '0.9.10'
}
...

With the Gradle task jibDockerBuild we can create a Docker image for our local Docker. Our project is called springboot-sample with version 1.0.0-SNAPSHOT, so we get the Docker image springboot-sample:1.0.0-SNAPSHOT:

$ ./gradlew jibDockerBuild
Tagging image with generated image reference springboot-sample:1.0.0-SNAPSHOT. If you'd like to specify a different tag, you can set the jib.to.image parameter in your build.gradle, or use the --image=<MY IMAGE> commandline flag.
warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible

Containerizing application to Docker daemon as springboot-sample:1.0.0-SNAPSHOT...

Getting base image gcr.io/distroless/java...
Building dependencies layer...
Building resources layer...
Building classes layer...
Finalizing...
Loading to Docker daemon...

Container entrypoint set to [java, -cp, /app/resources/:/app/classes/:/app/libs/*, mrhaki.spring.sample.SampleApplication]

Built image to Docker daemon as springboot-sample:1.0.0-SNAPSHOT

BUILD SUCCESSFUL in 3s
3 actionable tasks: 1 executed, 2 up-to-date
$

Notice that the default image our Docker image is build on is gcr.io/distroless/java, but we can change that in our Gradle build file via the jib configuration block.

Our image is available so we can run a Docker container based on our image and check the URL of our application:

$ docker run -d --name springboot-sample -p 8080:8080 springboot-sample:1.0.0-SNAPSHOT
5d288cbe4ed606760a51157734349135d4d4562072e1024f4585dff370ac6f99
$ curl -X GET http://localhost:8080/message
Spring Boot sample application.
$

In the following example we add some configuration for Jib in our Gradle build file:

// File: build.gradle
...
jib {
    to {
        image = "springboot-mrhaki:${project.version}"
    }

    container {
        // Set JVM options.
        jvmFlags = ['-XX:+UnlockExperimentalVMOptions', '-XX:+UseCGroupMemoryLimitForHeap', '-Dserver.port=9000']
        // Expose different port.
        ports = ['9000']
        // Add labels.
        labels = [maintainer: 'mrhaki']
    }

}
...

When we run the jibDockerBuild task a new Docker image is build:

$ warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible

Containerizing application to Docker daemon as springboot-mrhaki:1.0.0-SNAPSHOT...

Getting base image gcr.io/distroless/java...
Building dependencies layer...
Building resources layer...
Building classes layer...
Finalizing...
Loading to Docker daemon...

Container entrypoint set to [java, -XX:+UnlockExperimentalVMOptions, -XX:+UseCGroupMemoryLimitForHeap, -Dserver.port=9000, -cp, /app/resources/:/app/classes/:/app/libs/*, mrhaki.spring.sample.SampleApplication]

Built image to Docker daemon as springboot-mrhaki:1.0.0-SNAPSHOT

BUILD SUCCESSFUL in 3s
3 actionable tasks: 1 executed, 2 up-to-date
$ docker run -d --name springboot-mrhaki -p 9000:9000 springboot-mrhaki:1.0.0-SNAPSHOT
6966ff3b5ca8dae658d59e39c0f26c11d22af7e04e02ad423516572eb5e0e0bd
$ curl -X GET http://localhost:9000/message
Spring Boot sample application.
$

Jib also adds the jib task to deploy a Docker image to a registry instead of the local Docker daemon. Jib can use several command-line applications to authenticate with registries or we can set authentication information in the Gradle build file. Check Jib on Github for more documentation of the options and features.

Written with Spring Boot 2.0.4.RELEASE and Jib Gradle plugin 0.9.10.

September 21, 2015

Spring Sweets: Java System Properties As Configuration Properties With Spring Boot

In a previous post we learned that configuration property values can be passed via environment variables. With Spring Boot we can also pass the values using Java system properties. So if we have a property sample.message then we can use -Dsample.message=value to pass a value when we run the application. If we use the Spring Boot Gradle plugin we must reconfigure the bootRun task to pass Java system properties from the command-line.

Let's reuse our sample application from the previous blog post:

package com.mrhaki.spring

import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.stereotype.Controller

@SpringBootApplication
@Controller
class Application implements CommandLineRunner {

    @Value('${sample.message:"default"}')
    String message

    @Override
    void run(final String... args) throws Exception {
        println "Spring Boot says: $message"
    }

    static void main(String[] args) {
        SpringApplication.run(Application, args)
    }

}

Our Gradle build file now looks like this:

buildscript {
    repositories.jcenter()

    dependencies {
        classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE'
    }
}

apply plugin: 'groovy'
apply plugin: 'spring-boot'

repositories.jcenter()

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.4.4'
    compile 'org.springframework.boot:spring-boot-starter'
}

// Reconfigure bootRun task to pass
// along the Java system properties
// from the command-line.
bootRun {
    systemProperties System.properties
}

Now we can run the following command from the command-line and set a value for the sample.message configuration property:

$ gradle -Dsample.message="Set by Java sys prop." -q bootRun
...
Spring Boot says: Set by Java sys prop.
...
$ 

Written with Spring Boot 1.2.5.RELEASE and Gradle 2.7.