Docker Basics and Easy Steps to Dockerize Spring Boot Application

Sohee Kim
7 min readMay 28, 2021

--

Have you ever said “My application runs perfectly on my laptop, but not when I deploy in the cloud.” or “My colleague and I have the same code base. It works on my colleague’s laptop, but it doesn’t work on my local laptop.”?

Wouldn’t it be lovely if you can magically encapsulate your environment along with your code and share or deploy it as a whole package?

Luckily, Docker can exactly do that for you.

In this post, I’d like to share what I’ve learned so far about Docker and answer questions like “What is Docker?”, “How does Docker work?”, and “How to use Docker?”.

Section I : Basic Concepts of Docker and Containers
Section II : Dockerize a Spring Boot Application
Section III : Side Notes

Photo by Robin M. on Unsplash

I’d like to start by quickly going over what Docker and containers are. For those who are familiar with these concepts, please move on to the next section!

Section I : Basic Concepts of Docker and Containers

Q: What is Docker?

A: Docker is an open-source containerization platform.

Q: What is Containerization?

A: Containerization is simply a way of packaging software applications into containers.

Q: What are Containers?

A: Containers are executable units of software. They package everything your application needs including the code, libraries, and dependencies so that your application can run anywhere, in any environment. Containers do this by taking a form of OS virtualization and simply borrowing the resources (CPU, memory, and disk) of the host OS in isolated processes.

The level of virtualization is the key difference between virtual machines (VMs) and containers. Virtual Machines virtualize the physical hardware, so each VM has to contain a guest OS. However, since containers virtualize the OS, they don’t need a guest OS. The absence of a guest OS is why containers are so lightweight, fast, and portable.

Container vs VM from Docker Official Website

Q: What are the benefits of using Containers?

  • Portable: Once you containerize your application, you can run it in any environment whether it is on someone else’s laptop or in the cloud without having to re-configure. Using containers for deployment, you can achieve deployment portability and consistency.
  • Efficiency: Containers enable engineers to maximize the physical machine’s CPU and memory usage since application components can be deployed and scaled in small container blocks. This is especially relevant to using containers in microservice architectures.
  • Modernize Applications: As containers are lightweight and portable, they are suitable for cloud-native and microservice architectures.

Hello, Docker!

Since Docker’s release in 2013, it has totally changed how engineers play with containers. Now, Docker is almost used interchangeably with containers and is the de facto way of utilizing containers.

At runtime, the Docker engine starts containers using a read-only template called Docker images. A Docker image is created based on a Dockerfile, which is simply a text-based script file.

Q: What’s so special about Docker?

Docker uses a custom containerization technology, enabling engineers to use containers in a lighter, faster, and more efficient way.

  • Image Layering: A Docker image is inevitably bulky because it contains all information including the code and configuration files to run a container. Docker solves this by image layering. When you add or edit a file, Docker creates a new image layer instead of creating a new Docker image from scratch. All you need to do is download a new image layer.
  • Docker Hub: Docker has a great place to upload or download Container Images — Docker Hub. According to the website, there are 100,000+ container images. You can use these images as the base image which works as a template. Basically, this allows you to reuse existing containers.
  • Dockerfile: Dockerfiles are easy to read and write. Using Dockerfiles to maintain your dependencies and configuration, you can easily “manage your infrastructure in the same ways you manage your applications.
  • Versioning: Similar to how Github works, Docker keeps the history of container images. You can easily track versions and roll back container images.

In short, Docker helps you to deliver your application fast and consistently. I recommend reading Docker Docs and IBM Container to learn more.

In the next section, I will create and run a Docker container for a Spring Boot application.

Section II : Dockerize a Spring Boot Application

Docker should be installed and running. If it’s not installed, you can install it here.

In this tutorial, we will follow these steps:

  1. Create a Spring Boot Application
  2. Create Dockerfile
  3. Build executable jar file
  4. Build Docker image
  5. Run Docker container using the image built
  6. Test

Let’s start!

1. Create a Spring Boot Project

I created a very simple Spring Boot application. Feel free to create your own or use mine from Github.

There’s one endpoint that takes a name as a path variable and asks a simple question, “do you like banana pudding?” (btw, I love banana pudding!)

If I run my application and send a request, this is what I get!

2. Create a Dockerfile

Create a Dockerfile at the root folder.

Let’s go line by line to understand what each step is doing.

FROM

To build a Docker image using a Dockerfile, we need a base image layer. Since my application is written in Java, we have to build an image based on a Java image. Thus, FROM adoptopenjdk/openjdk15:ubi means that the image we are creating is based on a Java 15 OpenJDK image.

ENV

This sets the environmental variable. APP_HOME=/usr/app/ simply assigns the directory /usr/app/ to APP_HOME. This value is used for CMD.

WORKDIR

This is the directory where the output of CMD should run. In my case, it will be /usr/app/ .

COPY

This copies the file or a directory to the container’s directory. Thus, COPY build/libs/*.jar app.jar means to copy build/libs/*.jar to the container’s app.jar.

EXPOSE

Expose sets the port number to connect to the host.

CMD

When the container is created using docker run or gets started using docker start, it runs this command. The format is CMD ["fileToRun", "param1", "param2"] . Thus, CMD [“java”, “-jar”, “app.jar”] means to run the shell command line java -jar app.jar when the container starts.

3. Build executable jar file

You can build an executable jar file by simply clicking on the Gradle build task on the left.

This results in an executable jar file at /build/libs/demo-0.01-SNAPSHOT.jar.

4. Build Docker Image

Now that we have an executable jar file and a Dockerfile, it’s time to build a Docker Image.

$ docker build -t bootdocker:1 .

  • Make sure to include . at the end
  • Here, -t simply means tag followed by ‘ name:tag ’ format.

After running the command, you can see that a Docker image is built.

You can $ docker images | grep bootdocker to check if the Docker image was built successfully.

5. Run Docker container using the image built

$ docker run -d --name bootdocker -p 8080:8080 bootdocker:1

-d means that we will start the container in a detached mode. It exits when the root process used to run the container exits.

-name assigns the name of the container.

-p exposes the container’s internal port. The format is -p hostPort:containerPort. The exposed container’s port can be directed through the specified host’s port. Thus, -p 8080:8080 binds the host’s 8080 port to the container’s internal 8080 port.

bootdocker:1 is the Image name along with the tag.

You can check with $ docker ps -a | grep {name} to check if the container is built successfully.

You can also have a look at the log file to see if my application ran successfully using $ docker logs -f bootdocker .

Looks great!

6. Test

If I send a request, I get exactly what I expect!

Hooray, we have just run a Dockerized Spring Boot application!

Section III : Side Notes

  • If you want to see if the jar file is correctly copied to the container’s given directory, you can use docker exec -it -w /usr/app bootdocker /bin/bash . Remember /usr/app is the APP_HOME I assigned in my Dockerfile.
  • These are some command lines I found useful.
$ docker run
$ docker start
$ docker ps -a
$ docker stop {containerID}
$ docker rm {containerID}
$ docker images

This article is written as a friendly introduction to Docker and to showcase how Docker works in a nutshell. For a more optimized solution, I recommend reading this tutorial. If there is anything you disagree with or want to add, please let me know. I’d love to learn more!

--

--