visit
Keep up with the latest and best practices to build spring boot docker images.
As a Java Developer I am sure you must have heard of spring boot and probably Docker as well. Docker is phenomenon that has taken DevOps world by a storm.Every new project and old one’s too are migrating to containers.In this tutorial I will cover brief description of Docker containers and the essential tips that will help you get most out of Docker with Spring Boot.Source code of the demo project is atThus your application works like it is in its own self contained environment, but it’s actually sharing operating system resources of the host computer. Because of this, containers are more resource efficient than full-blown virtual machines.
Clearly, this is more efficient computing than running a full blown Virtual Machine.Docker is an open-source project for automating the deployment of applications as portable, self-sufficient containers that can run on the cloud or on-premises.Google, Amazon and Microsoft deploy millions of containers every day.
Let’s begin this tutorial of deploying spring boot app on docker and 5 awesome tips for your docker build,Step 1: Create a Hello World App Spring Boot application
Our first step is to create a demo hello world application.I will be using below git repository for the spring boot app.If you are interested in learning about creating a beginner’s spring boot app have a look at this article.Step 2 : Adding Dockerfile
If you have downloaded github repo above, you would notice that we are using
Spring Boot 2.3.0
Spring Boot 2.3.0
comes with several changes in it’s support for docker.The most important one is using the layered design of docker to avoid large size of spring boot apps. We will look at that in tips section of this tutorial.Let’s add a sample
Dockerfile
,FROM openjdk:15-jdk-slim
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
docker build -t learnings/spring-boot-docker-demo
docker run -p 3050:3050 --name spring-boot-docker-demo -t learnings/spring-boot-docker-demo
docker build -t learnings/spring-boot-docker-demo .
docker history learnings/docker-spring-boot-demo
Tip 3 # : Build docker image from Maven Wrapper
Our docker build seems to be working but it is missing one key part,We are creating our fat jar files manually and then going to terminal torun docker build
mvn -N io.takari:maven:wrapper
FROM openjdk:15-jdk-slim as bulid
WORKDIR application
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
RUN cp /application/target/*.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract
FROM openjdk:15-jdk-slim
WORKDIR application
COPY --from=bulid application/dependencies/ ./
COPY --from=bulid application/spring-boot-loader/ ./
COPY --from=bulid application/snapshot-dependencies/ ./
COPY --from=bulid application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
Tip 4 # : Use a separete docker user
Docker runs it’s command in container as a root user,Just as in classic VM-deployments, processes should not be run with root permissions. Instead the image should contain a non-root user that runs the app.In a Dockerfile, this can be achieved by adding another layer that adds a (system) user and group, then set it as the current user (instead of the default, root):RUN addgroup demogroup && adduser --ingroup demogroup --disabled-password demo
USER demo
Tip 5 # : Caching build process using Docker build cache
We have added maven build process to our Dockerfile but there is one performance concern. Each time we run
docker bulid
, it runs and downloads the maven packages as it creates a new container every time.Docker has an experimental feature to avoid this,You can add below as your first line in Dockerfile to enable experimental features.# syntax=docker/dockerfile:experimental
RUN --mount=type=cache,target=/root/.m2 ./mvnw install -DskipTests
# syntax = docker/dockerfile:experimental
FROM openjdk:15-jdk-slim as bulid
RUN addgroup demogroup && adduser --ingroup demogroup --disabled-password demo
USER demo
WORKDIR application
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN --mount=type=cache,target=/root/.m2 ./mvnw install -DskipTests
RUN cp /application/target/*.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract
FROM openjdk:15-jdk-slim
WORKDIR application
COPY --from=bulid application/dependencies/ ./
COPY --from=bulid application/spring-boot-loader/ ./
COPY --from=bulid application/snapshot-dependencies/ ./
COPY --from=bulid application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
Error response from daemon: Dockerfile parse error line 13: Unknown flag: mount
We need to run the docker build with a special command to enable experimental features,DOCKER_BUILDKIT=1 docker build -t learnings/spring-boot-docker-demo .
=> [bulid 7/10] COPY src src 0.2s
=> [bulid 8/10] RUN --mount=type=cache,target=/root/.m2 ./mvnw install -DskipTests **57.3s**
=> [bulid 9/10] RUN cp /application/target/*.jar app.jar
=> CACHED [bulid 8/10] RUN --mount=type=cache,target=/root/.m2 ./mvnw install -DskipTests 0.0s
=> CACHED [bulid 9/10] RUN cp /application/target/*.jar app.jar 0.0s
=> CACHED [bulid 10/10] RUN java -Djarmode=layertools -jar app.jar extract 0.0s
0.0s
Previously published at