[1/3] Let’s Create a Spring Boot App with MySQL, Docker, Docker Compose
--
👋 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.
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.
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.--publish
or -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.--volume
or -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.
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' .
We can also see the created docker image using the docker images
command.
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.
☀️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
, environment
settings and complete the service. In addition, the dependencies between the services are specified with the “depends_on” parameter used here.
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
🧿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