Translate

Thursday, September 20, 2018

Spring Sweets: Dockerize Spring Boot Application With Jib

Source: https://dzone.com/articles/spring-sweets-dockerize-spring-boot-application-wi

Spring Sweets: Dockerize Spring Boot Application With Jib


Creating Docker images for Java applications just became a lot easier. Let's take a look at how to use Jib to accomplish this goal quickly and easily with Jib.           

by Hubert Klein Ikkink
Jib is an open-source Java library from Google designed for creating Docker images for Java applications. Jib can be used as a Maven or Gradle plugin in our Spring Boot projects. One of the nice features of Jib is that it adds layers to our classes, resources, and dependency libraries for the Docker image. This means that when only class files have changed, the classes layer is rebuilt, 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 in this sample Spring Boot application. We will use Gradle as a 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 built on 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 can 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 built:
$ 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 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.