Using Docker Compose in Spring Boot 3

Docker has revolutionalized the application development with easy-to-use containers that can run on any machine and provide seamlessly consistent behavior in each environment. Docker Compose allows defining the multiple containers in a YAML file that the application depends on. These containers can be databases, message queues or even network services.

This article discusses how to start all the docker containers when the application starts; and shut down all containers when the application stops.

1. Docker Compose Support in Spring Boot

Since version 3.1, Spring boot provides a new module ‘spring-boot-docker-compose‘ that directly integrates with Docker Compose.

As a prequisite, the ‘docker compose‘ or ‘docker-compose CLI‘ application must be present on the path. Spring boot uses the commands that are executed using this application.

1.1. Maven

To use the module, include the following dependency:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-docker-compose</artifactId>
  <optional>true</optional>
</dependency>

1.2. Features

The new module provides the following features:

  • Checks for a docker-compose file in the project’s root directory. The file is searched with names:
    • compose.yaml
    • compose.yml
    • docker-compose.yaml
    • docker-compose.yml
  • When the application starts, containers/services defined in the compose file are started using the command “docker compose up“.
  • The service connection beans are created for each supported container.
  • When the application stops, containers/services defined in the compose file are shut down using the command “docker compose down“.
docker compose up  # when the application starts

docker compose down # when the application shuts down

2. Docker Compose File

2.1. File Name and Location

By default, the compose file is looked into the project’s root. To use a file with a different name or location, set the spring.docker.compose.file property. The file path can be an exact path or relative to the root.

spring.docker.compose.file = ./docker/compose.yaml

If the default or specified compose file is not found, java.lang.IllegalStateException is thrown:

java.lang.IllegalStateException: No Docker Compose file found in directory 
  'C:\Users\lokesh\IdeaProjects\Spring-Boot-Examples\.'

2.2. Active Profile

We can also create spring profile specific compose files. Spring boot will execute the compose file based on the active profile only.

  • dockercompose-local.yaml # local development profile
  • dockercompose-dev.yaml # dev profile
  • dockercompose-test.yaml # test profile

We can activate a specific profile using the following property:

spring.docker.compose.profiles.active = dev

3. Other Customizations

The module supports a few more customizations using the properties:

3.1. Waiting for Containers to Start

Docker containers may take time to install/start. By default, Spring boot waits for all the services and containers to start. Note that a container is considered ready when a TCP/IP connection can be established to its mapped port.

If we want to turn off this behavior for a particular container(s), we can use the org.springframework.boot.readiness-check.tcp.disable property as follows:

services:
  redis:
    image: 'redis'
    ports:
      - '6379'
    labels:
      org.springframework.boot.readiness-check.tcp.disable: true

3.2. Timeouts

It is also possible to configure different timeouts using the respective properties.

spring.docker.compose.readiness.tcp.read-timeout=200ms        #Timeout for reads
spring.docker.compose.readiness.tcp.connect-timeout=200ms     #Timeout for connections

spring.docker.compose.readiness.timeout=2m     #Timeout of the readiness checks
spring.docker.compose.readiness.wait=always    #Wait strategy to use

3.3. Lifecycle

The Docker Compose lifecycle is controlled by the following property:

spring.docker.compose.lifecycle-management = start-and-stop

It can have either of the three values:

  • none – Do not start or stop Docker Compose
  • start-only – Start Docker Compose when the application starts and leave it running
  • start-and-stop – Start Docker Compose when the application starts and stop it when the JVM exits

4. Demo

For demo purposes, we are creating a new Spring boot application with a single dependency:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-docker-compose</artifactId>
  <optional>true</optional>
</dependency>

Next, we created a docker-compose.yaml file with the following content:

services:
  redis:
    image: 'redis'
    ports:
      - '6379'

Now, start the application and notice the logs. The application downloads the docker images, starts the container and then the application is fully started.

INFO 25644 --- [           main] com.howtodoinjava.demo.App               : Starting App using Java 17.0.1 with PID 25644 (C:\Users\lokes\IdeaProjects\Spring-Boot-Examples\spring-boot-docker-compose\target\classes started by lokesh in C:\Users\lokes\IdeaProjects\Spring-Boot-Examples)
2023-05-30T13:08:00.218+05:30  INFO 25644 --- [           main] com.howtodoinjava.demo.App               : No active profile set, falling back to 1 default profile: "default"
2023-05-30T13:08:00.321+05:30  INFO 25644 --- [           main] .s.b.d.c.l.DockerComposeLifecycleManager : Using Docker Compose file 'C:\Users\lokes\IdeaProjects\Spring-Boot-Examples\spring-boot-docker-compose\docker-compose.yaml'
2023-05-30T13:08:01.742+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  redis Pulling 
2023-05-30T13:08:06.034+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  f03b40093957 Pulling fs layer 
2023-05-30T13:08:06.034+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  8db26c5e8435 Pulling fs layer 

...
...
...

2023-05-30T13:08:12.639+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  635073d8ccd5 Pull complete 
2023-05-30T13:08:12.704+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  redis Pulled 
2023-05-30T13:08:12.718+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  Network spring-boot-docker-compose_default  Creating
2023-05-30T13:08:12.785+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  Network spring-boot-docker-compose_default  Created
2023-05-30T13:08:12.785+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  Container spring-boot-docker-compose-redis-1  Creating
2023-05-30T13:08:13.618+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  Container spring-boot-docker-compose-redis-1  Created
2023-05-30T13:08:13.624+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  Container spring-boot-docker-compose-redis-1  Starting
2023-05-30T13:08:14.149+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  Container spring-boot-docker-compose-redis-1  Started
2023-05-30T13:08:14.149+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  Container spring-boot-docker-compose-redis-1  Waiting
2023-05-30T13:08:14.668+05:30  INFO 25644 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli   :  Container spring-boot-docker-compose-redis-1  Healthy
2023-05-30T13:08:16.091+05:30  INFO 25644 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-05-30T13:08:16.100+05:30  INFO 25644 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-05-30T13:08:16.101+05:30  INFO 25644 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.8]
2023-05-30T13:08:16.194+05:30  INFO 25644 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-05-30T13:08:16.195+05:30  INFO 25644 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1100 ms
2023-05-30T13:08:16.623+05:30  INFO 25644 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-05-30T13:08:16.633+05:30  INFO 25644 --- [           main] com.howtodoinjava.demo.App               : Started App in 16.819 

5. Conclusion

In this Spring boot docker compose tutorial, we learned to use the inbuilt docker compose module in Spring boot. We learned to customize the compose file and its lifecycle with an example.

Happy Learning !!

Sourcecode on Github

Comments

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.