Creating docker images in spring boot using build packs

Praveen G. Nair
4 min readJun 26, 2020
Springboot dockerization with cloudnative support.

This tutorial is a continued episode for my last blog. In this blog, we would go through the new feature Spring Boot 2.3.0 introduced for building Spring Boot docker images using Cloud Native Buildpacks (CNB). We will try to understand the process and behavior pros and cons at the end too. First lets try to understand what is Cloud Native Build packs and its role. Lets get started…

Cloud Native Buildpacks

CNBs are the part of the platform that take our application and convert it into something that the platform can actually run. Behind the scenes, a buildpack retrieves dependencies, processes assets, handles caching, and compiles code for whatever language your app is built-in. CNBs combines the simplicity and usability of buildpacks with the benefits of containers, which produce an OCI-compliant image that works with existing Docker tooling and the broader container ecosystem.

Buildpacks were tightly coupled to the platform and we couldn’t easily use them independently. But recently, they have been made free, and with Cloud Native Buildpacks we can use them to create Docker compatible images that we can run anywhere. CNB also allows the developer to avoid writing and maintaining docker files.

Ways to Create Docker Image

As discussed in my previous post, apart from JIB Plugin, there are maven plugins like Spotify docker plugin and fabric8 docker plugin for creating docker images. These are most traditional way convert the fat jars produced by Spring Boot into Docker images, using a “Dockerfile”. A simple Dockerfile looks like this:

Dockerfile

Although it is relatively easy to make the Docker image, though sometimes it is not always an optimized way.

The first problem with the above docker file is that the jar file is not unpacked. As such, there is always a certain amount of overhead when running a fat jar in a docker environment.

The second issue with the file is that it isn’t very efficient if we frequently update our application. In this case, since our application and all its dependencies are put into a single layer, the Docker image is built every time from scratch which consumes time. Hence, the Docker layers are not utilized optimally. However, if we put the dependent jar files in the layer before our application classes, then Docker will only need to change the very bottom layer and can pick others up from its cache.

Two new features introduced from Spring Boot 2.3.0 onwards, can help improve on these drawbacks: buildpack support and layered jars.

Now lets see an example for this.We are building a sample spring boot REST service will create a Docker image for our project. Later we would see how we can layer support. Layering reduces the docker image size. we would go through layering in detail in our next blog.

Spring Boot 2.3.X includes buildpack support directly for both Maven and Gradle. This means we can just type a single command and quickly create a Docker image.

Build the Image

Now let’s get our application source code compiled, packaged and converted to a Docker image using the Spring Boot Maven plugin and buildpacks.

We can also customize the name of the Docker image. By default, the name of the image is based on the artifactId and the version of the Maven project:

docker.io/library/${project.artifactId}:{project.version}

To customize the image name we can provide the name inside the image tag in the configuration section of the Spring Boot Maven plugin.

maven plugin

Proceed to build the Docker image as follows:

$ mvn spring-boot:build-image

You would see image generated once build completes.

docker image.

We can also push this image to Dockerhub using the below command:

docker push prgnr173/springboot-buildpack-app

Run the App Using Docker

Let us start the Container using the below command:

$ docker run -p 8080:8080 prgnr173/springboot-buildpack-app

Verify container is up in docker shell, by running

$ docker ps

Once the container is verified, hit the rest endpoint http://localhost:8080/ to view our application up and running.

Running app

This shows that the application is successfully running in the container.

These are very bare minimum steps we used and created our Docker image using Cloud Native Buildpacks. We can further optimize the Docker image using layering steps.

Summary

So we have seen different ways to create docker image. And now we can compare and contrast based on bare minimum prerequisites.

Comparison

I would stand with Google’s Jib as it doesn't require any docker daemon or docker file to get started for building docker images. But if your enviroment needs support for customization then spring boot cloudpacks is also a choice.

As usual I have shared the code here. Happy learning !!

--

--

Praveen G. Nair

I am a Software Developer and a Technologist. Interested in all cool stuffs of software development, Machine Learning and Cloud. https://praveeng-nair.web.app/