New versions of Spring Boot provide easy ways to build Docker images without using any third-party libraries or services such as Spotify Maven plugin or Jib. In this tutorial, we cover how to build Docker images in Spring Boot 3.
The good old dockerfile
approach
The most common approach to building a Docker image is using a Dockerfile as below,
FROM amazoncorretto:11
EXPOSE 8080
ARG JAR_FILE=target/app.jar
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Then run,
$ docker build -t app:latest .
However, this approach has some disadvantages:
- The image size is larger
- The application startup time is slower
Buildpacks for Spring Boot 3
Starting from Spring Boot 2.3, one can build a Docker image for a Spring Boot app without using any dockerfile
or external libraries with a single command.
$ mvn spring-boot:build-image
For Gradle projects,
$ gradle bootBuildImage
Despite being simple and straightforward, this approach does not have much flexibility. For instance, one cannot add an environment variable easily with or customize the Docker image. It is suitable for vanilla Spring Boot projects.
Layered Jars with custom dockerfile
for Spring Boot 3
We can still take advantage of faster startup time and smaller image size by using the Layered Jars approach. Spring Boot 2.3 and newer versions (including Spring Boot 3.x) provide a new type of “fat jar” format called LAYERED_JAR
in which the lib
and classes
directories have been split up and categorized into layers.
This approach empowers us to create a dockerfile
that extracts and copies each layer of the fat jar to a Docker image while giving us ultimate flexibility.
To achieve that, first, we need to enable the layered jar as follows,
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>
Now we can create a dockerfile
that takes advantage of the layered jar and customize it to our needs,
FROM amazoncorretto:17 as builder
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM amazoncorretto:17
COPY --from=builder dependencies/ ./
COPY --from=builder snapshot-dependencies/ ./
COPY --from=builder spring-boot-loader/ ./
COPY --from=builder application/ ./
ENV API_SECRET_KEY=place_holder
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
Finally, we can build the image,
$ mvn spring-boot:build-image -Dspring-boot.build-image.imageName="app":"1.2.3"
Spring Boot doesn’t provide an approach to push the image to Docker Hub. Instead, we need to use the docker
command as follows,
$ docker login -u "username" --password-stdin <<< "password"
$ docker push "app" --all-tags &&
Conclusion
In this tutorial, we covered how to build Docker images with Spring Boot 3. Starting with Spring Boot 2.3, one can utilize the tools, namely buildpacks
and layered jars
for creating Docker images without using any third-party libraries.
For simple use cases, the recommended approach is buildpacks
since one can build the image only with a single command.
For complex cases, one can combine a custom dockerfile
with the layered jar
approach that provides faster startup time and a smaller image size.
The fully functional demo project is available on GitHub at the link below,
https://github.com/kasramp/spring-data-redis-example-kotlin
Inline/featured images credits
- Featured image by Valdas Miskinis from Pixabay