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 at https://github.com/avinash10584/spring-boot-docker-demo.git So what are these containers ? Many view containers as virtual machines. They’re not. Well, kind of not. A container is a virtual walled environment for your application. It’s literally a ‘container’ inside the host OS. Thus your application works like it is in its own self contained environment, but Because of this, containers are more resource efficient than full-blown virtual machines. it’s actually sharing operating system resources of the host computer. 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. Because containers require far fewer resources (for example, they don’t need a full OS), they’re easy to deploy and they start fast. This allows you to have higher density, meaning that it allows you to run more services on the same hardware unit, thereby reducing costs. This efficient mechanism is used by most cloud providers to save them of resources. 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. https://github.com/avinash10584/spring-boot-docker-demo.git If you are interested in learning about creating a beginner’s spring boot app have a look at this article. https://medium.com/codingfullstack/spring-boot-microservice-on-cloud-create-shopping-list-service-part-1-9ea531054be5 Step 2 : Adding Dockerfile If you have downloaded github repo above, you would notice that we are using Spring Boot 2.3.0 comes with several changes in it’s support for docker. Spring Boot 2.3.0 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 openjdk: -jdk-slim JAR_FILE=target/*.jar FROM 15 ARG COPY app.jar ${JAR_FILE} ENTRYPOINT [ , , ] "java" "-jar" "/app.jar" Run mvn package from your IDE or terminal to generate the spring boot fat jar. Make sure you have spring boot maven plugin added to generate the fat jar. org.springframework.boot spring-boot-maven-plugin < > build < > plugins < > plugin < > groupId </ > groupId < > artifactId </ > artifactId </ > plugin </ > plugins </ > build Now let’s run below docker command to build the image, -t learnings/spring- docker build boot-docker-demo This will create an image in Docker registry, Let’s run this Docker image as a container, docker -p 3050:3050 --name spring- -docker-demo -t learnings/spring- -docker-demo run boot boot Docker layers allows us to keep our build images small in size as we make changes to our application. If our application code is changed then only application/application layer is affected and other layers stay cached. You can verify it by making changes to the RestController and running the docker build. -t learnings/spring- . docker build boot-docker-demo Check the history of your image to notice that the newly created images are in KB’s, docker learnings/docker-spring-boot-demo history 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 to run docker build This will not work with your CI/CD pipelines as you would need to do your maven build in your CI/CD tool. We can combine these two steps in either direction, We can use a maven plugin to generate the docker image during maven build Or, We can use maven wrapper to call maven build from inside our Dockerfile. I prefer using maven wrapper so I will use that here, Make sure you have Maven before below steps, go to your project directory and run mvn -N io.takari:maven: wrapper This will install the maven wrapper in your project. Maven 3.7 plans to integrate this to Maven by default. Add maven wrapper instructions to Dockerfile and build again, openjdk: -jdk-slim as bulid openjdk: -jdk-slim FROM 15 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 15 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" No need to run maven build anymore before bjuilding your docker images. 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): addgroup demogroup && adduser --ingroup demogroup --disabled-password demo demo RUN USER 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 , it runs and downloads the maven packages as it creates a new container every time. docker bulid 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 We need to also add below to specify that we want to cache the mount before we run maven build =type=cache,target=/root/.m2 ./mvnw install -DskipTests RUN --mount Our final Dockerfile loos like below, openjdk: -jdk-slim as bulid demo openjdk: -jdk-slim # syntax = docker/dockerfile:experimental FROM 15 RUN addgroup demogroup &amp;&amp; adduser --ingroup demogroup --disabled-password demo USER WORKDIR application COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN --mount= =cache,target=/root/.m2 ./mvnw install -DskipTests type RUN cp /application/target/*.jar app.jar RUN java -Djarmode=layertools -jar app.jar extract FROM 15 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" If you run it you will probably see the error, 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 -t learnings/spring- . DOCKER_BUILDKIT =1 build boot-docker-demo First time I ran this, my maven build step took almost a minute, => [bulid / ] COPY src src s => [bulid / ] RUN --mount= =cache,target=/root/. ./mvnw install -DskipTests ** s** => [bulid / ] RUN cp /application/target/*.jar app.jar 7 10 0.2 8 10 type m2 57.3 9 10 On the next run I could see the builds running almost instantaneously, => CACHED [bulid / ] RUN --mount= =cache,target=/root/. ./mvnw install -DskipTests s => CACHED [bulid / ] RUN cp /application/target/*.jar app.jar s => CACHED [bulid / ] RUN java -Djarmode=layertools -jar app.jar extract s s 8 10 type m2 0.0 9 10 0.0 10 10 0.0 0.0 We have successfully reduced build time in our docker images. That’s all folks, as you can see we have implemented a spring boot app from scratch and learned the tips that will help ypu take your build with Docker to next level. If you have any questions or feedback don’t hesitate to write your thoughts in the comments/responses section. For issues related to code, feel free please create an issue directly in GitHub repository. https://github.com/avinash10584/spring-boot-docker-demo.git Thank you for reading! If you enjoyed it, please share/comment for it. Previously published at https://medium.com/codingfullstack/5-essential-docker-tips-for-your-spring-boot-images-8f570270d9ba