Spring Boot + Mongodb + Docker Compose

unsplash-logoGabriel Barletta
In this post we will discuss how to use Docker Compose to define and run multi-container Docker applications.
The code for this post is available on my Github account here

Prerequisites
To Follow along this post basic knowledge of Docker, Container & Spring Boot is Needed. docker and docker-compose should be install on your system.

Docker Compose
Docker Compose is a tool for defining and running multi-container Docker applications. We define and configure all the services used in application in single file called as “docker-compose.yml” More details about docker compose can be found in documentation. Docker compose helps and reduces lot of overhead of managing apps that has dependancy on multiple containers.
Docker compose significantly improves productivity as we can run complete application stack using single command. Docker compose runs all the containers on a single host by default.

Docker Compose in Action
I will create simple hypothetical application that will expose rest endpoint to manage fruit information. Application is build using two containers. I will use docker compose to run this multi-container application.

Spring Boot APP
Create very Spring Spring boot application using Spring initializr use below dependency. spring-boot-starter-web,spring-boot-starter-actuator,lombok and you should be able to run the application.Check http://localhost:8080/actuator/health point is returning status as “UP”

Dokcrizeing spring boot app
Dockerizing Spring Boot app is very straightforward,below is sample Dockerfile file.

1
2
3
4
5
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

Creating Docker Image
docker build -t api-docker-image .
Run above command to create docker image. There are maven plugins available for creating docker image during maven build. for simplicity i am using simple docker command to create image.

Running Docker Image
docker run -d -p 9090:8080 api-docker-image
we are mapping 8080 container port to 9090 host machine port means the application will be available on host machine on port 9090. Now Spring boot application is running on docker and will be available on
http://localhost:9090/actuator/health

Now let’s add mongodb
Add below dependancy in pom file

Pom File
1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

Rest endpoints to save and get Fruit information.

Rest Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@RestController
@Slf4j
public class FruitController {

private final FruitService fruitService;
public FruitController(FruitService fruitService) {this.fruitService = fruitService;}

@PostMapping("/fruits")
public ResponseEntity addFruit(@RequestBody FruitRequest fruitRequest) {
log.info("Request : {}", fruitRequest);
fruitService.saveFruit(fruitRequest.toFruitModel());
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@GetMapping("/fruits")
public List<FruitModel> getAllFruit() {
return fruitService.findAll();
}
}
}

Simple JPA MongoRepository for saving and getting data to/from mongodb

JPA Repository & Fruit JPA Model
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component
public interface FruitRepository extends MongoRepository<FruitModel ,String> {
}

@Document
@Data
@Builder
public class FruitModel {

@Id
private String id;
private String name;
private String color;
}
}

Now we want to run mongodb database as separate container and spring boot app as separate container application. We can do this manually by running docker commands, But that’s very tedious task and lot of configurations needed for containers to talk to each other. docker compose simplifies these things for us

Define services in a Compose file
We Create a file called docker-compose.yml and starts defining all the containers needed for application as services.
in below docker compose file we are defining two services one is for database and one for rest-api and we do all the needed configuration at single place. As our spring boot app (api) is dependent on database we are specifying that as link. There are lof configuration we can do in docker compose file.

docker-compose
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: "3"
services:
api-database:
image: mongo:3.2.4
container_name: "api-database"
ports:
- 27017:27017
command: --smallfiles
api:
image: api-docker-image
ports:
- 9091:8080
links:
- api-database
}

Configure mongodb host name using spring config property using service name defined in docker-compose.

docker-compose
1
spring.data.mongodb.host=api-database

Running Docker Compose
docker-compose up single command is needed to start the application. command will create one container for database and one for spring-boot app as defined in docker-compose file.

Summary

Using Compose is basically a three-step process:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.

  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.

  3. Run docker-compose up and Compose starts and runs your entire app.

The code for this post is available on my Github account here

Share Comments