How to Dockerize Spring Boot and MongoDB Project with Microservice Architecture?

Mert Bahardoğan
9 min readJan 7, 2022

A Spring Boot project will be Dockerized which uses Microservice Architecture and MongoDB.

Introduction

We will use and mention Microservice Architecture, Layered Architecture, RESTful API Design, NoSQL Database, Docker, Docker-Compose, Swagger, and more.

Requirements

  • JDK (11)
  • Maven (3.8.1)
  • IDE (IntelliJ IDEA)
  • MongoDB (5.0.3)
  • Docker Desktop (20.10.11)

You can choose some different options.

GitHub Repository

Unfortunately, I cannot add the whole code. If you want to learn more about the project details you can check my GitHub.

Feel free to give stars if you enjoyed this article. I would appreciate it if you open an issue or contribute to the repository. It will always be better together!

What is Microservice Architecture?

Microservices are a distributed and loosely coupled version of monolithic architecture. It also has many benefits, but only when it is used in the right situations. Some of these benefits are independence, scalability, maintainability, and testability. Microservices should observe and apply the principles like single responsibility, loose coupling, and high cohesion.

What is NoSQL?

NoSQL is a high-performance, non-relational database with flexible data models. It is preferred when scalability, low latency, and high availability are needed. There are some types of NoSQL databases like Key-Value, Document (MongoDB), Graph, and Column-Oriented.

If you want to understand NoSQL in-depth, you should search CAP theorem and BASE approach.

Creating a Spring Boot Application

Let’s see how to create our Microservice Architecture in Spring Boot. I will use just a microservice but if you want to learn how to use multiple microservices and communication between these, contact me.

We are moving forward with Spring Initializr and applying in the following picture. I’ve used Spring Boot 2.6.2 because it was a stable version at that time.

This website generates Spring Boot Project.

Now we can open the downloaded project in IDE. As you can see, dependencies were not added when creating the project because I want to add the required dependencies using Maven Dependency Management manually and create our package structure subsequently.

The module was added into the microservices-project main project folder for using Microservice Architecture as you see below. We are going to use Layered Architecture in our microservice, let’s see how it was implemented.

The folder structure must be like this.

Layered Architecture, is a well-established software application architecture that separates the responsibilities. It is divided into 3 main headings that try to explain our project.

  • Presentation Layer: The purpose of the Presentation Layer is to display and collect information from the client. API package corresponds to Presentation Layer.
  • Business Layer: The purpose of the Business Layer which is the heart of the project contains business codes, rules, and logic that are implemented here. business package corresponds to Business Layer.
  • Persistence Layer: It transforms the business object into database domain models and contains Data Access Objects (DAO). dataAccess packages correspond to Persistence Layer.
  • Data Layer: The purpose of the Data Layer is to perform CRUD (Create, Read, Update, Delete) operations in the database. entity packages correspond to the Data Layer.

In addition, we could have different Layered Architecture structures. What matters is the logical separation of codes.

Let’s add main dependencies for managing all microservices dependencies in microservices-project/pom.xml and Product Microservice dependencies in product/pom.xml.

@SpringBootApplication annotation includes @Configuration, @EnableAutoConfiguration, and @ComponentScan which indicates a configuration class that declares one or more Bean methods. @EnableMongoRepositories annotation required for using MongoDB repositories that indicates the Spring.

As you can see above, created Swagger which provides interface and documentation of API’s implementation methods and the main method of the project. In order to run the Application, you will use Product Microservice.

I have presented only one of the APIs which has been used in the application.

The Lombok package which configures entities has been used. @Data annotation contains@RequiredArgsConstructor, @Getters, @Setters, @ToString, @EqualsAndHashCode. So, we do not need to add these annotations manually because they have already been added.

@Document annotation is used to set the collection name. If the collection does not exist, it will be created. It is called the Code First approach. @Id annotation indicates that the field is the Primary Key of the Collection. If you need to configure any field, you can use @Field annotation.

Entity Package

@Repository annotation creates a bean for MongoRepository by Spring. Existing methods were used but we could also write our methods. @Query annotation can also be used to specify custom queries.

Repository Package

@Service annotation indicates that the business logic are located here.

Abstracts (Business) Package

Dependency Injection is providing the instances that a manager class needs instead of constructing them itself. The classes that are applied will be more loosely coupled. I prefer to use the most popular alternative of Dependency Injection techniques, Constructor Injection in between 4–9 lines.

Concretes (Business) Package

@RestController annotation includes @Controller,@ResponseBody and it handles every request that introduced for using RESTful web services. @RequestMapping annotation is used for routing in controller classes.

API Package

As you can see, general application settings are identified under the Application Settings comment line. Database Settings and Other Settings are also identified under their comment lines. I would like to point out that other settings were added because of a bug that occurred between Spring and SpringFox.

The application is ready for running in the Product Application class. Our first API is available in Swagger or Localhost. If localhost is selected, HTTP Request should be sent correctly otherwise an error will have occurred (HTTP 405 Method Not Allowed).

Recources File

The Spring Boot part has been completed. We can start the most important part of this project. I would like to explain Docker and the purpose of usage.

What is Docker?

Docker is the most popular open-source container technology. It provides; easy installation, running, testing, deploying, and maintaining of our applications. There are a lot of reasons for using Docker but the most significant reason is that the application could be used in every environment. If you want to learn Docker commands, click here. Let’s dive deeper.

Docker Image can be called a template with instructions for creating a Docker Container which is the packaged version of the application. We can create and publish our Docker Images or use other ones on the Docker Hub.

Docker Container is running or stopped version of the Docker Image and covers it. It is a structure in which we can manage runtime dependencies and provides process isolation with less resource consumption without using the virtualization of the operating system.

Dockerfile is a text document file used to specify a base image to Docker. The file name must be Dockerfile and there is no extension. Every line in Dockerfile represents a layer.

Docker Compose is a .yml-based file that provides multiple containers that can be run and stopped with a single command. It consists of 4 main partitions which are version, services, networks and volumes.

The application will be dockerized, then Docker Compose will be created. Docker Desktop must be started during these operations.

Just to dockerize using Dockerfile, we have to replace the 7th line of the application.properties file with the text below. It cannot be localhost anymore because the application and the database will not be running on the same host.

spring.data.mongodb.host=host.docker.internal

The application must be built for dockerizing due to the row identified /target/product-0.0.1-SNAPSHOT.jar in Dockerfile as seen in the following code snippet. Make sure that you are on the right path (..\microservices-project) and run the following command. After that, you will see BUILD SUCCESS the output and a jar file will be created under the target folder.

mvn clean install

Dockerfile must be created in the Product Module.

  • FROM corresponds to the name of the base Docker Image. In this example openjdk:11 is suitable.
  • EXPOSE determines the port address where the container is running in Docker.
  • COPY copies the specified files to the specified destination in the Docker Image.
  • CMD arranges the working order that executes the commands and parameters written in it.

Go to ..\microservices-project\product path and run the following command for dockerizing the application. . the dot at the end shows that it will put the image which will be created in the same folder. Here we write whatever we want the tag name after -t.

docker build -t product-service .

We can see the product-service image in the Images tab of Docker Desktop.

product-service Image

After that, the following command should be running to set up port redirection at the host.

docker run -p 8000:8000 product-service

We can see the product-service container in the Containers/Apps tab of Docker Desktop.

product-service Container

busy_mendel name has been assigned the container as the default name by Docker. Also if we want to assign a special name and run it in detached mode, the following command can be run. Detach mode means the container runs in the background and is it shown as -d.

docker run --name=product-container -dp 8000:8000 product-service

You could make a request again from Swagger or anywhere, the application will be ready for that in the container.

If any change in the application, these processes must be repeated from the beginning. I am going to write a new article about CI/CD Pipeline to avoid this repetition.

Let’s stop the application in Docker Desktop before continuing.

  • version Docker Compose version. services include product-service and product-database.
  • build makes the Dockerfile run and extracts the image in product-service.
  • depends_on makes the product-database written first run.
  • environmentcontains the variables of application.properties file because Docker does not see this file.

It is necessary to mention information for the communication between containers. The backend and the database containers have to communicate with same host. We did not define network and Docker will create default (bridge) network for these containers.

We must run the Dockerfile in the same path. The second file name is docker-compose.yml, which is the Docker Compose file.

docker-compose -f docker-compose.yml up

As I said first, the product-database is pulled from the specified mongo image then the product-service is pulled from the Dockerfile. Now the product is running in Docker Compose!

Docker Compose

Additional: Dockerizing without Dockerfile

Here I will just describe the easy Docker Image creation way. The application can be dockerized using the spring-boot-maven-plugin without Dockerfile. We just need to make some additions in the part between the build tags of theproduct/pom.xml.

As you can see below, The part inside the configuration and executions tags has been added. If you would like to compare the old and new versions, you can reach out here.

We will run the mvn clean install code in the terminal. The process may take a long time than the normal build process. After this process is finished, the Docker Image is in Docker Desktop. As you know, the Docker Image can run as a Docker Container and add a Docker Compose file to this image.

Conclusion

In conclusion, we created the Spring Boot Project and use other new technologies in this article. If you like this article please do not forget to drop a comment and like. Thank you for your attention. I also want to say thanks to Bekir Can Baykal for his support.

While I am writing my articles, I assume that you know some basics. Nevertheless, if you have any questions which are related to these topics, please do not hesitate to contact me via Email or LinkedIn.

Reference Resources

--

--

Mert Bahardoğan

Software Engineer at Trendyol | Co-Organizer of Türkiye Java Community