Share:

In Episode 2 of Containerize This!  (read the first post here) we look at how to Dockerize a Java Spring Boot Application. Java applications are built to be compartmentalized, making them a great contender for Docker.

It’s Simple

To get a Java application up and running, not a lot of steps are required. In many cases, all you need to do is have Java run your jar file and make sure your application is up and running. Throw these steps into a Dockerfile and bam! Your Java application has been Dockerized.

FROM java:8
ARG JAR_FILE
ADD ${JAR_FILE} javaspring-1.0.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

Not So Fast

Java applications are constantly changing and in a week, that jar file used in the Dockerfile could become obsolete. Luckily, Palantir and Spotify created Gradle and Maven plugins to integrate with Docker. These allow you to rebuild and push your Docker image. No changes need to be made to your Dockerfile and everyone is happy.

But Can We Do Better?

Using the Gradle and Maven plugins are a great way to integrate your Java application with Docker, but is it the best way? These plugins add extra dependencies to your pom file and falling into the black hole of trying to figure out what dependency is breaking your build is not fun at all. In the version of the Dockerfile-maven plugin used to build my Spring Boot Application with Maven, I found dependencies on specific versions of org.codehaus.plexus and javax.activation which caused build errors. Fixing those dependency errors was not fun.

The extra dependencies on top of the fact that Spring Boot Applications create large jar files means the docker images will also be fairly large. Can we get the docker image size smaller?

Yes We Can!

Docker introduced multistage builds which allows multiple FROM statements in one Dockerfile. This enables reuse of artifacts from one stage to another so they do not have to be built twice. Multistage can also be used to build the jar and run the Java application all in one file. This means that rather than having a Maven/Gradle plugin that drives Docker, Docker can drive Maven/Gradle to build the project.

Show Me The Code

FROM maven:3.5-jdk-8-alpine AS build 
COPY /src /usr/src/javaspring/src
COPY pom.xml /usr/src/javaspring
COPY Dockerfile /usr/src/javaspring
RUN mvn -f /usr/src/javaspring/pom.xml clean install


FROM openjdk:8-jre-alpine
COPY --from=build /usr/src/javaspring/target/javaspring-1.0.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

Here we use Maven to build the jar file in the first stage. In the second stage, we use an Alpine based openjdk instead of java to create a smaller image. We take the jar file created in the first stage and run the file with java. Aaand we’re done. It was simple! Make an API call.

Try It Yourself

How to test out my Spring Boot Application

1. Pull the image from Docker Hub.

docker pull avnipatel/javaspring:1.0

2. Run the dockerfile.

docker run -p 8080:8080 -t avnipatel/javaspring:1.0

3. Make an API call. Run the dockerfile.

https://localhost:8080/hello https://localhost:8080/tracks?artist=dnce

Read the first post in the Containerize This! series here. And read Part 3 here.

Want to learn more about how Containers can help your organization optimize and modernize your applications in the cloud? Read our eBooks:

Building Cloud-Native Applications with Containers and Azure Kubernetes

Modernize Your Applications with Containers on AWS