Dockerizing Spring Boot apps with Jib

· August 16, 2019

Jib is my preferred tool when it comes to dockerizing Spring Boot applications. Jib is pure Java which can create a docker image without Dockerfile and without a running Docker daemon by automatically uploading the image to a remote Docker Registry. It can also create a Docker image using a local Docker daemon.

Setup

Jib comes as a Maven and Gradle plugin. In this blog post we will use Maven.

<build>
    ...
    <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>jib-maven-plugin</artifactId>
        <version>1.4.0</version>
    </plugin>
    ...
</build>

Without Docker daemon

With the following command a docker image is created and then uploaded to Google Container Registry.

$ mvn clean install jib:build -Dimage=eu.gcr.io/altfatterz/docker-jib-demo

To examine network connectivity issues we can use:

$ mvn -X -DjibSerialize=true

In this case Jib is using the docker_credential_helper to retrieve the credentials for Google Container Registry. Using a Docker credential helper is the preferred way to set the credentials to a Container Registry instead of defining these credentials in your Maven settings. This approach is basically using gcloud, which is the recommended way to connect to a Google Container Registry, you only need to run gcloud auth configure-docker to set this up.

There is another more advanced way, using the docker-credential-gcr which you can setup following the Standalone Docker credential helper section of this documentation.

For AWS, Jib would use amazon-ecr-credential-helper and for Azure Container Registry acr-docker-credential-helper Docker credential helper.

With Docker daemon

Jib can also use the local Docker daemon:

$ mvn clean install jib:dockerBuild -Dimage=altfatterz/docker-jib-demo

By default Jib is using “Distroless” Docker Images as the base image. These are language focused docker images without any package managers, shells or any other programs you would expect to find in a standard Linux distribution.

You can easily change the base Docker image:

<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>jib-maven-plugin</artifactId>
    <version>${jib.version}</version>
    <configuration>
        <from>
            <image>openjdk:8-jre-alpine</image>
        </from>                
    </configuration>
</plugin>

Tags

You can easily tag the docker images, for example using the maven project version:

<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>jib-maven-plugin</artifactId>
    <version>${jib.version}</version>
    <configuration>
        <to>
            <tags>${project.version}</tags>
        </to>           
    </configuration>
</plugin>

Tags make it easy to manage versions of the docker images, an example using Google Container Registry

gcr-docker-jijb-demo

or with command line:

$ gcloud container images list-tags eu.gcr.io/altfatterz/docker-jib-demo

DIGEST        TAGS                   TIMESTAMP
26332d31fd4a  0.0.3-SNAPSHOT,latest  2019-08-16T16:48:03
9cf7c00784eb  0.0.2                  2019-08-16T16:46:11
9f8880641da7  0.0.1                  2019-08-16T16:45:23

Multi-layered images

Jib separates your application into multiple layers, as you can see with the following command:

$ docker inspect altfatterz/docker-jib-demo

[
    {
        "Id": "sha256:c5bcbd3183fb47c0ad709a787dc72af2dbdd958ce8f7fb9af8a94a0ea0bcf2e7",
        "RepoTags": [
            "docker-jib-demo:0.0.1-SNAPSHOT"
        ],
        ...
        "Config": {
            ...
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt",
                "JAVA_VERSION=8u222"
            ],
            ...
            "Entrypoint": [
                "java",
                "-cp",
                "/app/resources:/app/classes:/app/libs/*",
                "com.example.DockerJibDemoApplication"
            ],
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
                "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
                "sha256:6189abe095d53c1c9f2bfc8f50128ee876b9a5d10f9eda1564e5f5357d6ffe61",
                "sha256:24917f2870609331183d9702704a5555e4cdd1f1d36aae117637bcb415f76ff3",
                "sha256:66f04fc98f17b361d27144cdc9dc20597e43c969cad47503a95b5f29ae2074a0",
                "sha256:289eb806ed2e1a0c9a66a2fa539543c4b583ac483209c12b393664af4c18d396",
                "sha256:41ecf942828c5c4adbb1d11d52ae7941f0ad7cfa3699fc0afebdd3fd71669062"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

or with the following command:

$ docker history docker-jib-demo:0.0.1-SNAPSHOT

IMAGE               CREATED             CREATED BY               SIZE                COMMENT
c5bcbd3183fb        5 hours ago         jib-maven-plugin:1.4.0   1.03kB              classes
<missing>           5 hours ago         jib-maven-plugin:1.4.0   1B                  resources
<missing>           5 hours ago         jib-maven-plugin:1.4.0   16.7MB              dependencies
<missing>           49 years ago        bazel build ...          106MB
<missing>           49 years ago        bazel build ...          1.93MB
<missing>           49 years ago        bazel build ...          15.1MB
<missing>           49 years ago        bazel build ...          1.82MB

This makes sure that when only classes are changed only the classes layer will be rebuilt, causing very fast build times.

Jib Image Built 49 Years Ago?

You need to specify the following, otherwise the CREATED field will be 49 years ago

<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>jib-maven-plugin</artifactId>
    <version>1.5.1</version>
    <configuration>
        <container>
            <creationTime>USE_CURRENT_TIMESTAMP</creationTime>
        </container>          
    </configuration>
</plugin>

You can find the used example here: http://github.com/altfatterz/docker-jib-demo.git

Twitter