Docker Compose: MongoDB and Spring Boot example
Tags: docker, webdev, java, devops
Published: 2023-11-04 02:27:51

<a href="https://www.docker.com/">Docker</a> provides lightweight containers to run services in isolation from our infrastructure so we can deliver software quickly. In this tutorial, I will show you how to dockerize Spring Boot and MongoDB example using <a href="https://docs.docker.com/compose/">Docker Compose</a>.

Related Posts:
- <a href="https://www.bezkoder.com/spring-boot-mongodb-crud/">Spring Boot and MongoDB CRUD example</a>
- <a href="https://www.bezkoder.com/spring-boot-mongodb-reactive/">Spring Boot Reactive + MongoDB example</a>
- <a href="https://www.bezkoder.com/spring-boot-jwt-auth-mongodb/">Spring Boot, Spring Security, MongoDB: JWT Authentication example</a>
- Documentation: <a href="https://www.bezkoder.com/spring-boot-swagger-3/">Spring Boot Swagger 3 example</a>
- Caching: <a href="https://www.bezkoder.com/spring-boot-redis-cache-example/">Spring Boot Redis Cache example</a>

<h2>Overview</h2>
Assume that we have a Spring Boot Application working with MongoDB database.
The problem is to containerize a system that requires more than one Docker container:
<ul>
	<li>Spring Boot for Rest API</li>
	<li>MongoDB for database</li>
</ul>

Docker Compose helps us setup the system more easily and efficiently than with only Docker. We're gonna following these steps:
<ul>
	<li>Create Spring Boot App working with MongoDB database.</li>
	<li>Create Dockerfile for Spring Boot App.</li>
	<li>Write Docker Compose configurations in YAML file.</li>
	<li>Set Spring Boot Docker Compose Environment variables.</li>
	<li>Run the system.</li>
</ul>

Directory Structure:

![mongodb-docker-compose-spring-boot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/os00s1zgyqa4xs5rhtza.png)

<h2>Create Spring Boot App</h2>
You can read and get Github source code from one of following tutorials:
- <a href="https://www.bezkoder.com/spring-boot-mongodb-crud/">Spring Boot and MongoDB CRUD example</a>
- <a href="https://www.bezkoder.com/spring-boot-mongodb-reactive/">Spring Boot Reactive + MongoDB example</a>
- <a href="https://www.bezkoder.com/spring-boot-jwt-auth-mongodb/">Spring Boot, Spring Security, MongoDB: JWT Authentication example</a>

Using the code base above, we put the Spring Boot project in <strong>bezkoder-app</strong> folder without the need of <strong>resources</strong>/<em>application.properties</em>. It is because Environment variables will be exported to <em>.env</em> file.

<h2>Create Dockerfile for Spring Boot App</h2>
Dockerfile defines a list of commands that Docker uses for setting up the Spring Boot application environment. So we put the file in <strong>bezkoder-app</strong> folder.

Because we will use Docker Compose, we won't define all the configuration commands in this Dockerfile.

<strong>bezkoder-app</strong>/<em>Dockerfile</em>
```properties
# FROM maven:3.8.2-jdk-8 # for Java 8
FROM maven:3.8.5-openjdk-17

WORKDIR /bezkoder-app
COPY . .
RUN mvn clean install

CMD mvn spring-boot:run
```

Let me explain some points:
<ul>
	<li><code>FROM</code>: install the image of the Maven - JDK version.</li>
	<li><code>WORKDIR</code>: path of the working directory.</li>
	<li><code>COPY</code>: copy all the files inside the project directory to the container.</li>
	<li><code>RUN</code>: execute a command-line inside the container: <code>mvn clean install</code> to install the dependencies in <em>pom.xml</em>.</li>
	<li><code>CMD</code>: run script <code>mvn spring-boot:run</code> after the image is built.</li>
</ul>

<h2>Write Docker Compose configurations</h2>
On the root of the project directory, we're gonna create the <em>docker-compose.yml</em> file. Follow <a href="https://docs.docker.com/compose/compose-file/compose-file-v3/">version 3</a> syntax defined by Docker:

```properties
version: "3.8"

services:
  mongo_db:
    image: mongo:5.0.2
    restart: unless-stopped
    env_file: ./.env
    environment:
      - MONGO_INITDB_ROOT_USERNAME=$MONGODB_USER
      - MONGO_INITDB_ROOT_PASSWORD=$MONGODB_PASSWORD
    ports:
      - $MONGODB_LOCAL_PORT:$MONGODB_DOCKER_PORT
    volumes:
      - db:/data/db
  app:
    depends_on:
      - mongo_db
    build: ./bezkoder-app
    restart: on-failure
    env_file: ./.env
    ports:
      - $SPRING_LOCAL_PORT:$SPRING_DOCKER_PORT
    environment:
      SPRING_APPLICATION_JSON: '{
          "spring.data.mongodb.uri" : "mongodb://$MONGODB_USER:$MONGODB_PASSWORD@mongo_db:$MONGODB_DOCKER_PORT/$MONGODB_DATABASE?authSource=admin"
        }'
    volumes:
      - .m2:/root/.m2
    stdin_open: true
    tty: true

volumes:
  db:
```

- <strong>mongo_db</strong>:
<ul>
	<li><code>image</code>: official Docker image</li>
	<li><code>restart</code>: configure the <a href="https://docs.docker.com/config/containers/start-containers-automatically/#use-a-restart-policy">restart policy</a></li>
	<li><code>env_file</code>: specify our <em>.env</em> path that we will create later</li>
	<li><code>environment</code>: provide setting using environment variables</li>
	<li><code>ports</code>: specify ports will be used</li>
	<li><code>volumes</code>: map volume folders</li>
</ul>

- <strong>app</strong>:
<ul>
	<li><code><a href="https://docs.docker.com/compose/compose-file/compose-file-v3/#depends_on">depends_on</a></code>: dependency order, <strong>mongo_db</strong> is started before <strong>app</strong></li>
	<li><code>build</code>: configuration options that are applied at build time that we defined in the <em>Dockerfile</em> with relative path</li>
	<li><code>environment</code>: environmental variables that Spring Boot application uses</li>
	<li><code>stdin_open</code> and <code>tty</code>: keep open the terminal after building container</li>
</ul>

You should note that the host port (<code>LOCAL_PORT</code>) and the container port (<code>DOCKER_PORT</code>) is different. Networked service-to-service communication uses the container port, and the outside uses the host port.

<h2>Docker Compose Environment variables</h2>
In the service configuration, we used environmental variables defined inside the <em>.env</em> file. Now we start writing it.

<em>.env</em>
```properties
MONGODB_USER=root
MONGODB_PASSWORD=123456
MONGODB_DATABASE=bezkoder_db
MONGODB_LOCAL_PORT=7017
MONGODB_DOCKER_PORT=27017

SPRING_LOCAL_PORT=6868
SPRING_DOCKER_PORT=8080
```

<h2>Run the Spring Boot microservice with Docker Compose</h2>
We can easily run the whole with only a single command:
<code>docker compose up</code>

Docker will pull the MongoDB and Maven images (if our machine does not have it before).

The services can be run on the background with command:
<code>docker compose up -d</code>

```bash
$ docker compose up -d
[+] Running 11/11
 ✔ mongodb 10 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                                                                                                    
   ✔ 35807b77a593 Pull complete                                                                                                                                                                                     
   ✔ 664b0ebdcc07 Pull complete                                                                                                                                                                    
   ✔ d598f4d3c081 Pull complete                                                                                                                                                                      
   ✔ 291455135b00 Pull complete                                                                                                                                                              
   ✔ b46409342f13 Pull complete                                                                                                                                                                      
   ✔ ff2b9c6e6f3a Pull complete                                                                                                                                                              
   ✔ 149f6335fc27 Pull complete                                                                                                                                                                    
   ✔ baeb6f3bec76 Pull complete                                                                                                                                                                        
   ✔ 8617caab2de5 Pull complete                                                                                                                                                                       
   ✔ 067d70de7828 Pull complete                                                                                                                                                             
[+] Building 87.9s (9/9) FINISHED                                                                                                                                                                               docker:default
 => [app internal] load .dockerignore                                                                                                                                                         
 => => transferring context: 2B                                                                                                                                                                        
 => [app internal] load build definition from Dockerfile                                                                                                                                                
 => => transferring dockerfile: 238B                                                                                                                                                        
 => [app internal] load metadata for docker.io/library/maven:3.8.5-openjdk-17                                                                                                                            
 => [app 1/4] FROM docker.io/library/maven:3.8.5-openjdk-17@sha256:3a9c30b3af6278a8ae0007d3a3bf00fff80ec3ed7ae4eb9bfa1772853101549b                                                                     
 => [app internal] load build context                                                                                                                                                                            
 => => transferring context: 31.57kB                                                                                                                                                             
 => CACHED [app 2/4] WORKDIR /bezkoder-app                                                                                                                                                           
 => [app 3/4] COPY . .                                                                                                                                                                         
 => [app 4/4] RUN mvn clean install                                                                                                                                                                  
 => [app] exporting to image                                                                                                                                                                                 
 => => exporting layers                                                                                                                                                                              
 => => writing image sha256:c2f10209e87c064f039545b2e6812c9c15a405120d595d7e1ff888bd3cce267f                                                                                                            
 => => naming to docker.io/library/spring-boot-mongodb-app                                                                                                                                          
[+] Running 4/4                                                                                                                                                                                                                
 ✔ Network spring-boot-mongodb_default      Created                                                                                                                                            
 ✔ Volume "spring-boot-mongodb_db"          Created                                                                                                                                                     
 ✔ Container spring-boot-mongodb-mongodb-1  Started                                                                                                                                                  
 ✔ Container spring-boot-mongodb-app-1      Started
```

Now you can check the current working containers:

```bash
$ docker ps
CONTAINER ID   IMAGE                     COMMAND                  CREATED         STATUS         PORTS                                         NAMES
88af893b2a53   spring-boot-mongodb-app   "/usr/local/bin/mvn-…"   2 minutes ago   Up 2 minutes   0.0.0.0:6868->8080/tcp, :::6868->8080/tcp     spring-boot-mongodb-app-1
4ef8f9734878   mongo:5.0.2               "docker-entrypoint.s…"   2 minutes ago   Up 2 minutes   0.0.0.0:7017->27017/tcp, :::7017->27017/tcp   spring-boot-mongodb-mongodb-1
```

And Docker images:

```bash
$ docker images
REPOSITORY                 TAG       IMAGE ID       CREATED         SIZE
spring-boot-mongodb-app    latest    c2f10209e87c   2 minutes ago   912MB
mongo                      5.0.2     0bcbeb494bed   2 years ago     684MB
```

Send a HTTP request to the Spring Boot - MongoDB system:

![mongodb-docker-compose-spring-boot-api](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dt914lpbpq125a087dbd.png)

Check MongoDB Database:

```bash
$ docker exec -ti spring-boot-mongodb-mongodb-1 /bin/bash
root@2d71784ae3a9:/# mongo -u root -p 123456 --authenticationDatabase admin
MongoDB shell version v5.0.2
connecting to: mongodb://127.0.0.1:27017/?authSource=admin&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("742022a6-49ed-42dd-9a53-0fd156f234ec") }
MongoDB server version: 5.0.2

> show dbs
admin        0.000GB
bezkoder_db  0.000GB
config       0.000GB
local        0.000GB
> use bezkoder_db
switched to db bezkoder_db
> show collections
tutorials
> db.tutorials.find()
{ "_id" : ObjectId("6541dff55fa4083bdb3d0422"), "title" : "Docker Compose MongoDB Spring Boot", "description" : "Tut#1 Description", "published" : false, "_class" : "com.bezkoder.spring.data.mongodb.model.Tutorial" }
```

<h2>Stop the Application</h2>
Stopping all the running containers is also simple with a single command:
<code>docker compose down</code>

```bash
$ docker compose down
 ✔ Container spring-boot-mongodb-app-1       Removed
 ✔ Container spring-boot-mongodb-mongo_db-1  Removed
 ✔ Network spring-boot-mongodb_default       Removed    
```

If you need to stop and remove all containers, networks, and all images used by any service in <em>docker-compose.yml</em> file, use the command:
<code>docker compose down --rmi all</code>

```bash
$ docker compose down --rmi all
[+] Running 5/5
 ✔ Container spring-boot-mongodb-app-1       Removed
 ✔ Container spring-boot-mongodb-mongo_db-1  Removed
 ✔ Image spring-boot-mongodb-app:latest      Removed
 ✔ Image mongo:5.0.2                         Removed
 ✔ Network spring-boot-mongodb_default       Removed     
```

<h2>Conclusion</h2>
Today we've successfully created Docker Compose file for MongoDB and Spring Boot example. Now we can connect Spring Boot to MongoDB with Docker on a very simple way: <em>docker-compose.yml</em>.

You can apply this way to one of following project:
- <a href="https://www.bezkoder.com/spring-boot-mongodb-crud/">Spring Boot and MongoDB CRUD example</a>
- <a href="https://www.bezkoder.com/spring-boot-mongodb-reactive/">Spring Boot Reactive + MongoDB example</a>
- <a href="https://www.bezkoder.com/spring-boot-jwt-auth-mongodb/">Spring Boot, Spring Security, MongoDB: JWT Authentication example</a>

Happy Learning! See you again.

<h2>Source Code</h2>
The source code for this tutorial can be found at <a href="https://github.com/bezkoder/docker-compose-spring-boot-mongodb">Github</a>.

Documentation: <a href="https://www.bezkoder.com/spring-boot-swagger-3/">Spring Boot + Swagger 3 example (with OpenAPI 3)</a>
Caching: <a href="https://www.bezkoder.com/spring-boot-redis-cache-example/">Spring Boot Redis Cache example</a>