[1/3] Let’s Create a Spring Boot App with MySQL, Docker, Docker Compose

İlker Güldalı
7 min readFeb 23, 2022
source: giphy.com

👋 Hi everyone!

We will examine how to use Docker and Docker Compose on a Spring Boot — MySQL application and what adjustments are required.

Things we will fully experience with this series of articles:
👉[1/3] — Let’s Create a Spring Boot App With MySQL, Docker, Docker Compose
We will examine how to use Docker and Docker Compose on a Spring Boot — MySQL application and what adjustments are required.

✔️[2/3] — Push the Spring Boot App Docker Image to Docker Hub and Deploy to Digital Ocean Droplet
We’ll learn how to push previously locally created image to Docker Hub and simple way to deploy Digital Ocean Droplet.

✔️[3/3] — Deploy the Spring Boot App which is using Docker and Docker Compose in through “Github Actions” to a Digital Ocean Droplet
By implementing CI/CD processes into our project, we will experience making things a little easier.

The technologies we will generally use in this article are as follows. It is important for you to have 101 level knowledge about these in terms of understanding the series of articles.
These articles have been prepared to provide information about generally used concepts rather than being a step-by-step tutorial 😊

Tech Stack:

  • Spring Boot (2.6)
  • Docker (20.10.12)
  • Docker-Compose (2.2.3)
  • IntelliJ Idea (2021.3.1)
  • MySQL
  • Thymeleaf

Let’s Start!

Create a “Bored” Spring Boot App

We start by creating a Spring Boot project from start.spring.io or from IntelliJ Idea.

spring initializr settings

In this series of articles, we will work on an application that displays the data we receive through a public API(Bored API) on the homepage. In short, we will have an application that shows random activity suggestions for a bored person on the homepage. When click to “Create Activity” button, firstly new activity will be added to DB then user will redirect to homepage. Of course, our goal here is to examine Docker and Docker Compose rather than the utility of the application.💁‍♂️

The file hierarchy in the project is generally as follows.

“Bored App” file structure
“Bored App” file structure

There are configuration, controller, dto, model, repository and service packages in the main directory. In addition, the Dockerfile and docker-compose.yml files, which we will go into detail in the article, are also located in the main directory.

Creating a MySQL Container

We preferred using MySQL for database in “Bored App”. MySQL Docker image can be run with the following code on the command line.

If we look at the parameters in the command in detail:

--detach or -d: Docker runs the container in the background.
--publishor -p: It is the port information where the container will be published. The first value represents the port inside the host, while the second value represents the port inside the container.
--name : The name defined as custom to the container.
--volumeor -v : It allows the data in the container to be stored in the host and to share data between other containers. In our case, we added this parameter because we don’t want the created tables and the data in them to be lost every time the container is run again.
-e: The environment variables that will be passed to the container are provided with this parameter.
mysql:8.0 : Finally, the command is run by giving the image name and tag information.

Terminal output after “docker run” command

Creating a Docker File

First of all, a file with the name Dockerfile should be created in the main directory of the project. Then, similar to the example structure below, the appropriate fields for you need to be filled.

Here, in the first part, it is ensured that the related dependencies are downloaded and built over maven. Then the resulting .jar file is set as the entrypoint of the Docker image.

--mount=type=cache,target=/root/.m2

With this parameter, which come from BuildKit, we have cached the /root/.m2 folder that maven checks to use dependencies. Thus, there will be no need for re-downloading each time an image is created and the image creation time will be reduced.

Since Docker v18.09, you can use BuildKit to caching dependencies. It allows to mounting caches that can persist between builds. By the way, you can avoid downloading contents of the corresponding .m2 folder every time. (To enable BuildKit and for more information, check here)

Finally, the Docker image is created by running the command below.

docker build -t 'ilkerguldali/boredapp:latest' .
Terminal output after “docker build” command

We can also see the created docker image using the docker imagescommand.

Image files created on Docker

Hint: Don’t forget to add the --no-cache parameter to the docker build command if you want the maven dependencies to be downloaded again, not through the cache!

🏃The Final Step!

Finally, by running the command below, we make the relevant docker image accessible from port 8080.

docker run -d -p 8080:8080 --name bored-app --link bored-db ilkerguldali/boredapp:latest

Hint: --link parameter is a necessary parameter for the containers to communicate with each other. (The parameter must be defined to both containers if two-sided communication is required.) By default, it provides one-way communication.

In order to use the container name in the connection string used when connecting to MySQL from the Spring Boot app, the legacy --link parameter or “user-defined” network must be used.

Containers on the default bridge network can only access each other by IP addresses, unless you use the --link option, which is considered legacy. On a user-defined bridge network, containers can resolve each other by name or alias.

Instead of using an legacy property, we can create a “user-defined” network to access containers by name or alias on inside of each other.

The image below shows how the above processes would proceed by creating a “user-defined” network without legacy “ — link” parameter.

Terminal output of creating a “user-defined” network and assigning it to containers.
Running state of Bored App

☀️Let’s make it easy with Docker-Compose!

As you can imagine, constantly building image and running container will make the process very difficult. At this point, docker-compose comes to our rescue, which does these things for us in a sequential and easy way.

We can automate the build of the images, we made above and the creation of the containers with the YAML file below.

MySQL DB Service

While in the project main directory, we create our file named docker-compose.yml and configure as above. Here, we first set the image, environment, port and volume settings for the MySQL DB. A new network definition is made under the network parameter that will be used in the bored-app. Containers operating on the same network can interact via container names. For example, in the environment under the bored-app service; like "MYSQL_HOST=bored-db"

Bored App Service

After the database setup, we specify the location of the relevant Dockerfile under the build parameter in the bored-app service. Then we make the container_name, network, environmentsettings and complete the service. In addition, the dependencies between the services are specified with the “depends_on” parameter used here.

Bored App application.properties file details

In the application.properties file of the spring boot application, the database related things are included in the parameter. Thus, when the application will be run with the container over the docker-compose file, it can be run with different parameters. At the same time, when it will run on the local machine, it has been made to work with default parameters.

With the command below, both the DB and the bored-app application will run over docker-compose.🥳

docker-compose up -d --build
Terminal output after “docker-compose up” command
Docker Desktop — Containers Screen

🧿Conclusion

In this article, I have generally explained how an application built with Spring Boot — MySQL will work with Docker and Docker Compose.

If you want to review the code sample:

If there is a part in the article that you see as incorrect or missing, make sure to contact me so that we can learn the right way :)

I hope I can bring the continuation of the article series mentioned at the beginning of the article. Each like is a “Yes! You can” support. 👍

Thanks for reading, 💃🏻have fun coding!

References

--

--