Before Spring Boot 3.1, if there were Docker containers supporting the application, we had to start the Docker containers first and then start the app.
But with Spring Boot 3.1, we can simplify this process by adding the following dependency:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-docker-compose</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Spring Boot 3.1 supports the following files for Docker Compose configuration:
Here's an example of a sample Docker Compose file:
version: '3.1'
services:
mysql:
image: mysql:8
container_name: mysql-8-server
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_DATABASE: testdb
ports:
- "3308:3306"
volumes:
- /Users/man/mysql_data:/var/lib/mysql
command: --default-authentication-plugin=mysql_native_password
To use a non-standard file, you can set the spring.docker.compose.file
property in your application.properties
or application.yaml
. For example:
spring.docker.compose.file=../<file name>.yml
From the logs:
2023-06-08T13:35:13.671+01:00 INFO 63741 --- [ restartedMain] .s.b.d.c.l.DockerComposeLifecycleManager : Using
Docker Compose file '/Users/man/workspace/test-containers-demo/compose.yaml'
2023-06-08T13:35:15.047+01:00 INFO 63741 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli : Container mysql-8-server Created
2023-06-08T13:35:15.049+01:00 INFO 63741 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli : Container mysql-8-server Starting
2023-06-08T13:35:15.736+01:00 INFO 63741 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli : Container mysql-8-server Started
2023-06-08T13:35:15.739+01:00 INFO 63741 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli : Container mysql-8-server Waiting
2023-06-08T13:35:16.243+01:00 INFO 63741 --- [utReader-stderr] o.s.boot.docker.compose.core.DockerCli : Container mysql-8-server Healthy
In addition, Spring Boot provides the capability to use Testcontainers during development. Testcontainers allows you to quickly start containers for the services your application depends on, such as database servers, eliminating the need for manual provisioning. To use Testcontainers, you can create a configuration class in the test package:
@Configuration
public class MySqlContainerDev {
@Bean
@ServiceConnection
@RestartScope
MySQLContainer mySQLContainer() {
return new MySQLContainer<>(DockerImageName.parse("mysql:latest"));
}
public static void main(String[] args) {
SpringApplication.from(TestContainersDemoApplication::main)
.with(MySqlContainerDev.class)
.run(args);
}
}
When executing MySqlContainerDev
, the logs will show the container startup:
2023-06-08T13:39:05.145+01:00 INFO 64013 --- [ restartedMain] tc.mysql:latest : Creating container for image: mysql:latest
2023-06-08T13:39:05.284+01:00 INFO 64013 --- [ restartedMain] tc.mysql:latest : Container mysql:latest is starting: fba51ec6d16d7afaa6ec3e9405bce1703463feac56916ed358f121ce709a742b
2023-06-08T13:39:05.892+01:00 INFO 64013 --- [ restartedMain] tc.mysql:latest : Waiting for database connection to become available at jdbc:mysql://192.168.64.19:49239/test using query 'SELECT 1'
2023-06-08T13:39:22.265+01:00 INFO 64013 --- [ restartedMain] tc.mysql:latest : Container mysql:latest started in PT17.120098S
2023-
06-08T13:39:22.271+01:00 INFO 64013 --- [ restartedMain] tc.mysql:latest : Container mysql:latest is healthy
In the logs, tc.mysql:latest
refers to the Testcontainer with the tag mysql:latest
.
With the @ServiceConnection
annotation, there is no need to use @DynamicPropertySource
to map the Spring Boot properties.
Before Spring Boot 3.1, we needed to map the Spring Boot properties when initializing test containers. For example:
static {
mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8-oracle"));
mysql.start();
}
@DynamicPropertySource
static void registerPgProperties(DynamicPropertyRegistry registry) {
if (mysql.isCreated()) {
registry.add("spring.datasource.url", mysql::getJdbcUrl);
registry.add("spring.datasource.username", mysql::getUsername);
registry.add("spring.datasource.password", mysql::getPassword);
}
}
By using the @ServiceConnection annotation, we no longer need to use @DynamicPropertySource.
This simplifies the configuration and eliminates the need for manual mapping of properties.
The `@RestartScope` annotation part of dev tools informs Spring Boot that the container has already started, preventing it from attempting to start it again.
Overall, Spring Boot's Docker Compose support and Testcontainers simplify the management of Docker containers and their integration with your Spring Boot application.