Spring Boot has released version 2.3.0 which adds support for Docker with build packs, layered images, graceful shutdown support, and liveliness, and uptime probes. Another notable change is the support for Java 14 while maintaining support for LTS 8 and 11 versions.

The Buildpacks are an alternative to Dockerfiles. Buildpacks automatically detects the requirements necessary to run the application in a Docker container. For example, it detects the version of Java used in the application. Based on this version, the build pack selects the JRE specified in the build pack and creates a Docker image. With Maven or Gradle, the following command creates a Docker image:

  • spring-boot:build-image

Note that no configuration was required to create a Docker image based on build packs.

It is possible to modify some build pack configurations using the bootBuildImage task. For example, the following Spring Boot Maven plug-in configuration in the build file shows how to change the name of the Docker image:

  • <configuration>
  • <image>
  • <name>infoq.com/${project.artifactId}:${project.version}</name>
  • </image>
  • </configuration>

Specifying the name of the Docker image can also be done from the command line:

  • mv/Gradle bootBuildImage –imageName=infoq.com/my-app:v1

Docker images work with layers. Adding the application artifact as the last layer reduces the on-disk size of the images. Developers typically store the application artifact as a JAR file. The downside is that the JAR file contains things that change often, like code. But the JAR file also contains things that change less frequently such as dependencies. Changes between versions in Docker images are stored as differences. When JAR files are stored for each version of the application, the difference is quite large and consumes a lot of disk space. Buildpacks reduce the space required by dividing

The functionality of dividing the artifact into multiple layers can also be used in a Dockerfile. Buildpacks offer some form of configuration, but Dockerfiles give the full control over the resulting image. Developers will therefore sometimes prefer a Dockerfile to a build pack. When choosing to use a Dockerfile, it is advisable to divide the layers of the artifact. It’s a bit more work than with a build pack, but it’s a one-time job.

First, configure the spring-boot-maven plugin to produce a layered JAR:

  • <build>
  • <plugins>
  • <plugin>
  • <groupId>org.springframework.boot</groupId>
  • <artifactId>spring-boot-maven-plugin</artifactId>
  • <configuration>
  • <layers>
  • <enabled>true</enabled>
  • </layers>
  • </configuration>
  • </plugin>
  • </plugins>
  • </build>

This plug-in configuration ensures that the application is divided into four parts: dependencies, spring-boot-loader, snapshot-dependencies, and application.

The excerpt below shows a multistage Dockerfile. In the first step, the application is executed with the specific argument Jarmode As a result, the four parts are stored in their directory. In the next step, these four directories are copied inside the Docker image in separate layers and the entry point is specified.

  • FROM adopt OpenJDK:14-JRE-hotspot as a builder
  • WORKDIR application
  • ARG JAR_FILE=target/*.jar
  • COPY ${JAR_FILE} application.jar
  • RUN java -Djarmode=layertools -jar application.jar extract
  • FROM adoptopenjdk:14-jre-hotspot
  • WORKDIR application
  • COPY –from=builder application/dependencies/ ./
  • COPY –from=builder application/spring-boot-loader/ ./
  • COPY –from=builder application/snapshot-dependencies/ ./
  • COPY –from=builder application/application/ ./
  • ENTRYPOINT [“java”, “org.springframework.boot.loader.JarLauncher”]

Developers can use the Dockerfile to create a Docker image and then run an image-based container:

  • docker build. –tag info
  • docker run -p8080:8080 info

Liveness and uptime probes are used by container systems like Kubernetes. Kubernetes starts a new pod when upgrading an app to a new version. This pod is started alongside the old pod which contains the old version. When the new pod is ready, it accepts traffic and the old pod is deleted. However, when the container is ready, the application is often not fully started. In the case of Spring Boot, it may take a few seconds. By default, this means that the new application, which is not fully started, is already receiving traffic, while the old application is stopped


This can be solved by querying a specific URL in the app that is available after starting the app. Whenever the URL is available, the app is ready to receive traffic and the old version can be removed. In Kubernetes, this can be implemented by a ReadinessProbe.

Spring Boot now offers uptime probe support by default, for example through the URL http: // localhost: 8080 / actuator / health / readiness which is exposed after enabling it in the app configuration : management.health.probes.enabled = true.


Besides ReadinessProbe, there is also the concept of a liveliness probe in Kubernetes. It is used to check if the application is still functioning correctly at a predefined interval. If the application does not respond, the module restarts. Spring Boot also offers an endpoint: Http: // localhost: 8080 / actuator / health / liveness .

These different endpoints work by default, but you can configure them: for example, to wait for a database to start.

A gradual shutdown is used to continue pending requests for some time after the application has stopped.

The following code snippet shows how to enable soft shutdown and configure the timeout value to 30 seconds:

  • shutdown=graceful
  • lifecycle.timeout-per-shutdown-phase=30s

This means that when stopping the application, new requests are not allowed. However, old queries still have 30 seconds to complete before the app is completely shut down.



Please enter your comment!
Please enter your name here