Ready to set up your Spring Boot Application with Docker? This guide covers everything from how Docker works to how you can install and use it with Spring Boot.
What is Docker?
Docker is a software platform for building applications based on containers: small and lightweight execution environments that make shared use of the operating system kernel but otherwise run in isolation from one another. While containers as a concept have been around for some time, Docker —an open source project launched in 2013 — helped popularize the technology and also helped drive the trend towards containerization and microservices in software development, which has come to be known as cloud-native development.
BUT WHAT ARE CONTAINERS?
One of the goals of modern software development is to keep applications on the same host or cluster isolated from one another so they don’t unduly interfere with each other’s operation or maintenance. This can be difficult, thanks to the packages, libraries, and other software components required for them to run. One solution to this problem is virtual machines, which keep applications on the same hardware entirely separate, reduce conflicts among software components, and keep competition for hardware resources to a minimum. But virtual machines are bulky (each requires its own OS, so it's typically gigabytes in size) and difficult to maintain and upgrade.
Containers, by contrast, isolate applications’ execution environments from one another but share the underlying OS kernel. They’re typically measured in megabytes, use far fewer resources than VMs, and start up almost immediately. They can be packed far more densely on the same hardware and spun up and down en masse with far less effort and overhead. Containers provide a highly efficient and highly granular mechanism for combining software components into the kinds of application and service stacks needed in a modern enterprise, as well as for keeping those software components updated and maintained.
The Difference Between VM and Docker:
Image courtesy of aquasec.
Remember: Docker is not a VM. They are quite different both in the way they work and in the contexts where they should be used. Read more about it here.
Important Docker Features
DOCKERFILE
Each Docker container starts with a Dockerfile. A Dockerfile is a text file written in an easy-to-understand syntax that includes the instructions to build a Docker image (more on that in a moment). A Dockerfile specifies the operating system that will underlie the container, along with the languages, environmental variables, file locations, network ports, and other components it needs—and, of course, what the container will actually be doing once we run it. Paige Niedringhaus at ITNext has a good breakdown of the syntax of a Dockerfile and examples. Check it out.
DOCKER IMAGE
Once you have your Dockerfile written, you invoke the Docker build utility to create an image based on that Dockerfile. Whereas the Dockerfile is the set of instructions that tells build how to make the image, a Docker image is a portable file containing the specifications for which software components the container will run and how. Because a Dockerfile will probably include instructions about grabbing some software packages from online repositories, you should take care to explicitly specify the proper versions, or else your Dockerfile might produce inconsistent images depending on when it’s invoked. But once an image is created, it’s static. Codefresh explains how to build an image in more detail, and it also offers more info on Dockerfiles.
DOCKER RUN
Docker’s run utility is the command that actually launches a container. Each container is an instance of an image. Containers are designed to be transient and temporary, but they can be stopped and restarted, which launches the container into the same state as when it was stopped. Furthermore, multiple container instances of the same image can be run simultaneously (as long as each container has a unique name). See examples here.
DOCKER HUB
While building containers is easy, don’t get the idea that you’ll need to build each and every one of your images from scratch. Docker Hub is a SaaS repository for sharing and managing containers where you will find official Docker images from open-source projects and software vendors and unofficial images from the general public. You can download container images containing useful code, or you can upload your own and share them openly or make them private. You can also create a local Docker registry if you prefer. (Docker Hub has had problems in the past with images that were uploaded with backdoors built into them.)
Dockerizing Your Spring Boot Application
One of the best visuals of how to Dockerize a Spring Boot Application may be found here, and I recommend that you watch the video and follow the instructions. Before you begin, however, please note that I ran into several problems while following the tutorial above; all of these problems can be resolved with the steps below:
1. First, create a Spring Boot application. If you have no idea where to start, I recommend this course.2. With your application ready, download and install Docker. There is no need to follow the tutorial on the Docker website.
3. If you feel the need, take this course to understand how Docker works.
Now let’s Dockerize your application.
4. Make sure Gradle is running on your project. You can check this by going to the IntelliJ terminal and running the command . \gradlew
After doing so, run Gradle clean build.
This will start Gradle on the project and create the following folders:
5. Create an application property, as shown below.
6. Create a Dockerfile, as shown below (I’m using Intellij for these examples).
Note that I’m clicking on the project folder and then new, file. Name your file as Dockerfile, with no extensions.
After creation, it will show up here:
7. After creating the Dockerfile, it's time to edit it.
There are many things you can put on your Dockerfile, depending on your needs. I found that the elements shown below are sufficient for a basic project.
Let’s break down each part of the image shown above:
FROM: put the version of Java you are using on your machine. I'm using this one.
ADD:
Image courtesy of educative.
Image courtesy of educative.
Please note that, in my example, build/libs/ indicates which folders you are going to get the jar file from. Feel free to change this according to your folders, if needed. After that, bookmanagement* indicates that every file named bookmanagement+ something else should be added. The app.jar name is the name for the application that we are setting on the container we are creating.
If you'd like more information on the Docker Add command, please reference this article.
EXPOSE: Define which ports you are going to expose on your docker container. In my case, 8080 is the main door, and 8083 is the one for tests.
ENTRYPOINT: Here I used entrypoint, but ENTRYPOINT and CMD give you a way to identify which executable should be run when a container is started from your image. In fact, if you want your image to be runnable (without additional docker run command line arguments), you must specify an ENTRYPOINT or CMD.
Trying to run an image which doesn't have an ENTRYPOINT or CMD declared will result in an error.
In this example:
Notice that we are defining “java”, the language, jar, the format, and the SAME NAME WE USED ON THE ADD COMMAND, which, here, is app.jar.
But please be aware that the proper and better way to finish things up is by using a docker-compose.yml file, which we'll explain below.
How to Dockerize the Application Without docker-compose.yml
Although finishing with docker-compose.yml is the better option, you can still Dockerize the application without a docker-compose.yml by taking the following actions:
1. Open two terminals side by side:
2. On the first terminal window, start your database. For this example, I’m using PostgreSQL, so the command is docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres
3. On the second terminal window, you need to create the Docker image. To do this, run the command docker build -f Dockerfile -t name-of-your-project . (THE DOT IS INCLUDED).
4. While you're still on the second terminal, get the image running with the command docker run -p 8080:8080 -p 8083:8083 name-of-your-project . (THE DOT IS INCLUDED).
Please note that the -p + port numbers are defining which ports you are exposing on the local machine and on the container. That is why you repeat the values. Remember that, in my case, 8080 is for standard connection, and 8083 is for tests.
And there you go, it should be running fine!
How to Dockerize the Application Using docker-compose.yml
What is docker-compose?
Docker Compose is a Docker tool used to define and run multi-container applications. With Compose, you use a YAML file to configure your application’s services and create all the app’s services from that configuration.
Think of docker-compose as an automated multi-container workflow. Compose is an excellent tool for development, testing, CI workflows, and staging environments. According to the Docker documentation, the most popular features of Docker Compose are:
- Multiple isolated environments on a single host;
- Preserve volume data when containers are created;
- Only recreate containers that have changed;
- Variables and moving a composition between environments; and
- Orchestrate multiple containers that work together.
Image courtesy of educative.
Using and Installing Docker Compose
Image courtesy of educative.
Educative details these steps:
- Define your app’s environment using a Dockerfile. This way, it can be reproduced. We did this already.
- Define the services for your app in a docker-compose.yml file. This way, they can run in an isolated environment.
- Run docker-compose to start your app.
To create the docker-compose, follow the same steps you took to create the Dockerfile, but name it docker-compose.yml. It will show up here:
Now let’s take a look at how to fill it using this example:
Image courtesy of educative.
And here is the meaning of everything:
Image courtesy of educative.
Fill your docker-compose with whatever you need.
For another example, my docker-compose looks like this:
Notice the network_mode: bridge is linking things between containers, in this case the application container and the database container.
Check if it's valid with the command docker-compose config
When it's ready, let’s get it running:
Use the command docker-compose up -d
(The -d is so you get it running on detached mode and get your bash prompt returned.)
Afterward, use the command docker ps to check that things are running correctly.
You can also see if it works in the docker app for your os. It should look like this:
and
If you need to drop the whole thing, use docker-compose down
If you need further help, watch this video or refer to this article.
Commonly-Used Docker-Compose Commands
Below is a list of useful docker-compose commands for you to reference:
All images courtesy of educative.
And that's all for today! I hope you enjoyed this introduction on how to install and use Docker on your Spring Boot Application.
References
"Docker Compose Tutorial: advanced Docker made simple." Amanda Fawcett, educative.
"How to build a Docker Compose file." Jack Wallen, TechRepublic.
"What is Docker Compose | How to create docker compose file | How to use Compose." Automation Step by Step, YouTube.
"Docker vs Virtual Machine -- Understanding the Differences." Avi, GEEKFLARE.
"What is Docker? The spark for the container revolution." Scott Carey, InfoWorld.
Author
Filipe Guimares