Dockerizing Spring Boot application and managing with Docker Compose: Part 1 — Building the image

Syed Hasan
5 min readApr 7, 2023

--

Agenda

This topic is split into 3 parts. The first part will focus on build the docker image of the application. In the 2nd part we will discuss on managing the containers with docker-compose. In the 3rd part, we will optimize our image to make the image lightweight by using some features shipped with JDK 9. The target readers of this article are required to have at least the ability of developing and running a Spring Boot application. Only dockerizing, managing optimizing docker image and running with docker compose will be covered.

The source code of the project can be found here.

This article will have 4 parts.

1. General discussion of the application structure

2. Writing Dockerfile to build a docker image of the implementation package

3. Building first docker image

General discussion of the application structure

Our application is a multi-module maven project. The parent pom.xml has the modules declaration of the sub modules. We have 2 submodules, 1 is bs-userinfo-definition and the other one is bs-userinfo-implementation.

In the bs-userinfo-definition module, we have our common interfaces and class definitions, that has been used from other services, like, bff-social-medium.

The bs-userinfo-implementation is out point of interest, which will be dockerized and deployed.

Building the application

From the folder where parent pom.xml resides, let’s run mvn clean install to generate the jar. The jar file will be found in the target folder of our bs-userinfo-implementation submodule.

Since, I don’t want the unit tests to run, I will also add argument skipTests

> mvn clean install -DskipTests

Our build is success, and we can see, the jar file has been generated in the target folder.

Writing Dockerfile to build a docker image of the implementation package

Now, inside the bs-userinfo-implementation, let’s create a Dockerfile and edit it.

Please note that, this is not the most optimized one, but it will do the job. Let’s learn about each line.

FROM — To build the docker image, we need a base image, which will provide the environment to run our image inside it. Alpine is a minimal version of Linux. openjdk:17-alpine is the openjdk image that has been installed inside an alpine linux image. With saying FROM openjdk:17-alpine we declared that we are using openjdk:17-alpine as our base image and we are now able to run java applications inside that image.

EXPOSE — With this instruction we say that we are going to expose our application to which port. Since our application will run on 8581 port inside docker container, therefore we are exposing 8581 port from inside the alpine image to outside of the image.

COPY — With this instruction we are saying that from our bs-userinfo-implementation submodule’s target folder, we want to copy any jar file that has prefix bs-userinfo-implementation-, we want to copy them inside the docker root directory and name as ROOT.jar

ENTRYPOINT — We send the bootstrapping / starting command with ENTRYPOINT instruction. We can also do similar thing with CMD instruction. But the main difference between CMD and ENTRYPOINT is, CMD can be used to pass additional command line arguments, where ENTRYPOINT is solely used for providing the command of application startup script.

To know more about the other instructions that we can use to write a Dockerfile, please see this cheat sheet.

Building first docker image

To build first docker image, we have to open terminal from the location where the Dockerfile exists. Well, we can also call the file from some other location and mention the file name while building the image, but that’s another story.

For now, we will open the terminal from the same directory as the Dockerfile. If your machine is windows, you can open it by Shift + Right Click of your mouse and click on Open PowerShell Window Here or, Open in Terminal

The generic command is like the following.

> docker build -f Dockerfile -t <your image name>:<tag> .

If you can remember, the base image that we used was openjdk:17-alpine, which has 2 parts separated by “:”. The first part was the image name, the 2nd part was the tag of the image. We will use a meaningful name for our image. The “.” at the end of the command means that we will build it from our current directory.

Note that, if you are using Linux, you may need to use sudo before the beginning of the command.

As we can see, our image has been created successfully without any error and named to bs-userinfo:1.0. Now let’s check our image.

If we notice the image name highlighted with yellow, we can see that our image was created 7 minutes ago, has the name bs-userinfo and tag 1.0, and size is 376MB. In our 3rd part of these article series, we will see how we can optimize this image size.

Keep in touch for the Part 2 to be published.

--

--

Syed Hasan
Syed Hasan

Written by Syed Hasan

Software Engineer | Back-End Developer | Spring Developer | Cloud Enthusiast

No responses yet