1. OVERVIEW

Ever since I published Microservices using Spring Boot, Jersey, Swagger and Docker, I had entertained the idea of making Package the service into a Docker image section its own blog post.

Back then I used Spotify’s docker-maven-plugin, which required connecting to a Docker host. Also felt it would have been almost identical to the section mentioned.

It was nice to learn Google released an open source tool named Jib aimed at easing containerizing Java applications. No need for a Dockerfile, no need for a Docker daemon, and actually no need for container expertise.

Packaging Spring Boot applications into Docker images using Jib

Although you could use Jib to build to a Docker daemon, this post focuses on building a Docker image for Spring Boot applications without requiring a Docker host.

2. REQUIREMENTS

  • Java 7+.
  • Maven 3.2+.

3. CREATE A SPRING BOOT 2 APPLICATION

Let’s create a Spring Boot 2 application to be shipped in a Docker image:

curl "https://start.spring.io/starter.tgz"
 -d name="springboot2-docker-demo"
 -d description="Simplifying Docker images for Spring Boot 2 apps"
 -d bootVersion=2.0.3.RELEASE
 -d dependencies=actuator,web
 -d language=java
 -d type=maven-project
 -d baseDir=springboot2-docker-demo
 -d groupId=com.asimio.demo
 -d artifactId=springboot2-docker-demo
 -d version=0-SNAPSHOT
 | tar -xzvf -

Let’s configure jib-maven-plugin Maven plugin in pom.xml:

...
<build>
  <plugins>
...
    <plugin>
      <groupId>com.google.cloud.tools</groupId>
      <artifactId>jib-maven-plugin</artifactId>
      <version>0.9.7</version>
      <configuration>
        <from>
          <image>openjdk:8u171-alpine</image>
<!--          <credHelper></credHelper> -->
        </from>
        <to>
          <image>asimio/${project.artifactId}:${project.version}</image>
<!--          <credHelper></credHelper> -->
        </to>
        <container>
          <jvmFlags>
            <jvmFlag>-Xms512m</jvmFlag>
            <jvmFlag>-Xmx512m</jvmFlag>
          </jvmFlags>
        </container>
      </configuration>
  </plugin>
...

The next section covers what these elements mean.

4. jib-maven-plugin CONFIGURATION EXPLAINED

configuration:

Element Type Default value Description
from from See from Configures which and how to access the base image
to to See to Configures the resulting image including the application
container container See container Configures the container that is run when using the result image


from configuration:

Element Type Default value Description
image String gtroless/javacr.io/dis The base image
credHelper String   Suffix for the credential helper docker-credential-<credHelper> to authenticate with the Docker registry to pull the base image from. Docker Hub when empty
auth auth   Alternative to credHelper credentials


to configuration:

Element Type Default value Description
image String Required The target image
credHelper String   Suffix for the credential helper docker-credential-<credHelper> to authenticate with the Docker registry to push the target image to. Docker Hub when empty
auth auth   Alternative to credHelper credentials


auth configuration:

Element Type
username String
password String


container configuration:

Element Type Default value Description
jvmFlags List   JVM arguments to be passed to the Java application
args List   Parameters to be passed to the main method of the Java application


See jib-maven-plugin’s Extended Usage tables for more options.

5. BUILDING THE DOCKER IMAGE USING JIB

  • Let’s first set a specific release version to the project instead of a snapshot before building it:
mvn clean versions:set -DnewVersion=1.0.1
...
[INFO] Processing com.asimio.demo:springboot2-docker-demo
[INFO]     Updating project com.asimio.demo:springboot2-docker-demo
[INFO]         from version 0-SNAPSHOT to 1.0.1
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
  • Now let’s build the Spring Boot artifact:
mvn package
...
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ springboot2-docker-demo ---
[INFO] Building jar: /Users/ootero/Downloads/ttt/springboot2-docker-demo/target/springboot2-docker-demo-1.0.1.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.0.3.RELEASE:repackage (default) @ springboot2-docker-demo ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
  • This step is not required to build a Docker image using Jib. Still, let’s export to a Docker context to take a look at how the application and its dependencies are laid out:
mvn jib:exportDockerContext
...
[INFO] --- jib-maven-plugin:0.9.7:exportDockerContext (default-cli) @ springboot2-docker-demo ---
[INFO] Created Docker context at /Users/ootero/Downloads/ttt/springboot2-docker-demo/target/jib-docker-context
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...

The Docker context is created at target/jib-docker-context unless -Djib.dockerDir VM argument is passed:

ls target/jib-docker-context/
Dockerfile	classes		libs		resources	snapshot-libs

This is how the Dockerfile looks like:

cat target/jib-docker-context/Dockerfile
FROM openjdk:8u171-alpine

COPY libs /app/libs/
COPY snapshot-libs /app/libs/
COPY resources /app/resources/
COPY classes /app/classes/

ENTRYPOINT ["java","-Xms512m","-Xmx512m","-cp","/app/libs/*:/app/resources/:/app/classes/","com.asimio.api.ApiDockerDemoApplication"]
CMD []

Notice jib-maven-plugin Maven plugin is extracting the application dependencies, properties files and classes. I wouldn’t expect this to be a problem for Spring Boot applications. Also, this plugin auto detects the main Java class.

  • As mentioned earlier, Jib can be also used to build to a Docker daemon. Even so, this blog post only covers building an image when Docker is not installed.
    Let’s then configure authentication in Maven’s settings.xml:
<settings>
...
  <servers>
...
    <server>
      <id>registry.hub.docker.com</id>
      <username>xxxx</username>
      <password>xxxx</password>
    </server>
...
  </servers>
...
</settings>

The id element should be set to the Docker registry server you would like to push the image to.

  • And finally, let’s build and push the Docker image:
mvn jib:build
...
[INFO] --- jib-maven-plugin:0.9.7:build (default-cli) @ springboot2-docker-demo ---
[INFO]
[INFO] Containerizing application to asimio/springboot2-docker-demo:1.0.1...
[INFO]
[INFO] Retrieving registry credentials for registry.hub.docker.com...
[INFO] Getting base image openjdk:8u171-alpine...
[INFO] Building dependencies layer...
[INFO] Building resources layer...
[INFO] Building classes layer...
[INFO] Retrieving registry credentials for registry.hub.docker.com...
[INFO] Finalizing...
[INFO]
[INFO] Container entrypoint set to [java, -Xms512m, -Xmx512m, -cp, /app/libs/*:/app/resources/:/app/classes/, com.asimio.api.ApiDockerDemoApplication]
[INFO]
[INFO] Built and pushed image as asimio/springboot2-docker-demo:1.0.1
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...

asimio/springboot2-docker-demo:1.0.1 image ia now available at https://hub.docker.com/r/asimio/springboot2-docker-demo/.

6. RUNNING A DOCKER CONTAINER

docker run asimio/springboot2-docker-demo:1.0.1
Unable to find image 'asimio/springboot2-docker-demo:1.0.1' locally
1.0.1: Pulling from asimio/springboot2-docker-demo
8e3ba11ec2a2: Pull complete
311ad0da4533: Pull complete
df312c74ce16: Pull complete
65d8ca522f0b: Pull complete
d36ff9619551: Pull complete
f9f857caf541: Pull complete
Digest: sha256:ce7afa5a5bb13bbdcd21107e9dccd2f7a4be2f8591e39df60c34c068a0f28b9d
Status: Downloaded newer image for asimio/springboot2-docker-demo:1.0.1
...
2018-07-31 04:42:49.101  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-07-31 04:42:49.109  INFO 1 --- [           main] com.asimio.api.ApiDockerDemoApplication  : Started ApiDockerDemoApplication in 7.426 seconds (JVM running for 8.273)

Successfully pulled the public image and started a container with a Spring Boot application.

Google’s Jib is still beta but under active development. Give Jib try, it’s a good alternative to Fabric8’s docker-maven-plugin, Spotify’s docker-maven-plugin and good old docker build -t ... command.

Stay tuned, I’ll also cover:

Thanks for reading and as always, feedback is very much appreciated. If you found this post helpful and would like to receive updates when content like this gets published, sign up to the newsletter.

7. SOURCE CODE

Accompanying source code for this blog post can be found at:

8. REFERENCES