Spring Boot Applications in Docker

Stories about project management and coding

Spring Boot Applications in Docker

As a beginner with Spring Boot, “dockerizing” a new application can look like a quite complicated task. In fact it is quite simple, using the right tools.
Dockerizing means nothing more than the putting your existing app, like a REST backend based on Spring Boot, into a docker image.
This post should not just be a step by step tutorial, I try to explain some of the backgrounds, as I believe no developer should put code he doesn’t understand into production.

Choosing the right base image

Deciding what base image to use is like deciding what server OS you want to use for running your software.
Docker Hub already has a lot of different images to offer, so it should always be your starting point. For many use cases there are already images that will fit your needs.
For Spring Boot you’ll obviously want to use an image that already has a Java runtime environment (JRE). You have to decide if you want to go with openjdk or if you need the Oracle JRE. It is still debated all over the net what the actual differences are, but since JRE7 I recommend to use openjdk, as long as you don’t need any of the proprietary stuff (like some fonts) packaged with Oracle JRE. At least with the openjdk you don’t have to fear that Oracle will come up with some weird licensing issue.
Head over to Docker Hubs page for the openjdk image to see your list of choices.

Next you have to decide if you need any tools from outside the JRE, like any Linux command line tools. If this is the case, you should go with the standard, Debian based, image. If not, I suggest to use the Alpine Linux based images, as they are lightweight and the end result is a much smaller image. The main caveat to note is that it does use musl libc instead of glibc and friends, so certain software might run into issues depending on the depth of their libc requirements. However, most software doesn’t have an issue with this, so this variant is usually a very safe choice. In the examples below I use the latest Alpine based, openjdk images, these come with the latest JRE 8.

The Dockerfile

From the official Docker documentation:

Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession.

I like to compare the Dockerfile to mavens pom.xml – it describes the build process.
When assembling a Spring Boot application, you will end up with a jar file, so all you have to do is tell the Docker build process to put the jar file into an image and tell it how to run it.
Here’s the easiest version that should suffice for most Spring Boot based applications:

I’ll explain what each lines does:

  1. FROM
    Tells Docker what base image we want to use.
    The VOLUME instruction creates a mount point with the specified name. I recommend to create the /tmp directory as some java libraries use it and with this you can save yourself some debugging later on.
  3. ADD <src>... <dest>
    Adds a file or directory to the image, without a path in the destination the file will be in the home directory (don’t worry about this too much for now)
  4. RUN
    Run a single command inside the image. I like to use touch to update the file access and modification times with every new build. (optional)
  5. ENV
    Any environment variables you might want to set. (optional)
    This tells docker how to start your application after the image was started. Here I use two recommended java options:

    1. -Djava.security.egd=file:/dev/./urandom
      Activates a much faster implementation for the SecureRandom provider. In some applications this can cut down the applications startup time in half.
    2. --spring.profiles.active=docker"
      Activates a designated Spring Profile. Head over to my post on Spring Profiles for more on this.

Now with your Dockerfile in place, you can run the build process with:

But wait a minute, because there is a much easier way to build the image.

Making use of Maven

As this post focuses on dockerizing a Spring Boot application, you might already have a Spring Boot based application with a pom.xml.
This enables you to also use Maven to build your Docker image, thanks to the awesome guys at Spotify who wrote the Maven plugin and open-sourced it.

Add the following to your pom.xml:

There are a few config parameters here that I want to explain:

  1. <properties> <docker.image.prefix>...
    This just the prefix for the image name.
  2. <imageName>...
    The name for your image (this will be in the output of docker images  later)
  3. <resource>...<targetPath>...<directory>...<include>....
    This tells the build process where your compiled app should reside, this has to match the paths and names in the Dockerfile mentioned above.
    ${project.build.finalName}  is part of mavens BaseBuild Element. It defaults to ${artifactId}-${version} . It can be overwritten, but usually it’s just something like my-project-1.0.jar .

Next, make sure to put your Dockerfile in the following directory, so the maven plugin is able to find it:

Maven Build

After you put the Dockerfile into the right directory and updated your pom.xml, run to following to create your very own Docker image:

Maven will pull the right plugins it needs for this goal and will run a maven build cycle of clean, compile, package and then build the Docker image.
Here’s an example output (Unit tests skipped for brevity):

That’s it – now you should be able to see your new image with docker images and fire it up:

Hope this helps, if you have any questions please leave a comment and I will update the article.

Tags: , , ,

One Response

  1. […] most of my projects I use Maven for building the packages and even for building the docker images. I was always to lazy to set up a continuous integration system for my private projects, mostly […]

Leave a Reply

Your email address will not be published. Required fields are marked *