Spring Boot 3 and Docker compose integration

Storing data the right way is one of the crucial parts of a web application. When building a Spring Boot application connected to a database, having a working database locally is not easy.

With Docker, starting a Docker container from the database image you want is simple, but this might still not be the best experience because you have to remember to start the Docker image and ensure it is up and running; let's not talk about remembering where the Docker volume is located.

Starting version 3.1 of Spring Boot, integration with Docker Compose is available to quickly set up your database and manage it from Spring Boot. This tutorial will show you how to configure the integration with Docker Compose for a MySQL database.

Prerequisites

To follow this tutorial, make sure you have the following tools installed on your computer.

Set up the project

We will start from the final project of the previous tutorial since it is the continuity. The project is in the blog repository GitHub.

We will do a sparse checkout to only clone the project folder we want in the Git repository.

Run the commands below to configure the project locally and launch it:


git clone --no-checkout https://github.com/tericcabrel/blog-tutorials.git

cd blog-tutorials

git sparse-checkout init --cone

git sparse-checkout set springboot-jwt-auth

git checkout @

mv springboot-jwt-auth springboot-docker-compose

cd springboot-docker-compose

mvn install -DskipTests

mvn spring-boot:run

The application will fail at the startup because the database is not available.

The Spring Boot application can't connect to the MySQL database.

Indeed, if you look at the application configuration file src/main/resources/application.properties, we can see the following database connection settings:


spring.datasource.url=jdbc:mysql://localhost:3307/taskdb?serverTimezone=UTC&allowPublicKeyRetrieval=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=secret

Database Host localhost
Database Port 3307
Database User root
Database Password secret

Let's see how to set this up using the Spring Boot integration for Docker Compose.

Configure the Docker compose file

At the project root directory, create a file compose.yaml and add the code below:


services:
  mysql:
    container_name: mysql
    image: mysql:8.0
    restart: unless-stopped
    volumes:
      - "./db-data:/var/lib/mysql"
    ports:
      - 3307:3306
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - MYSQL_DATABASE=taskdb


This file declares a new service named mysql from the MySQL Docker image and maps the container's port on port 3307 of the host. Finally, we set the MySQL password for the root user and give a database's name.

Install the Maven dependency

Let's install the Maven dependency, allowing Spring Boot to integrate with Docker Compose. Open the pom.xml and append the code below in the dependencies property.


<dependencies>
    <!-- Existing Maven package -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-docker-compose</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

Run the command below to resolve the dependency added:


mvn install -DskipTests

Run the Spring Boot application with Docker compose

The great thing about this integration is that it works out of the box; no configuration is required. When you start the application, Spring Boot will find any YAML file having the word "compose" in the file name.

Let's start the application and see the Docker compose integration in action:


mvn spring-boot:run

We get the following output:

Create the database Docker container at Spring Boot application startup.

In the above picture, you can see Spring Boot locate the Docker compose configuration file, start the Docker container, and log the update about the container lifecycle. Once the container is ready, the application can now start.

The application startup time is almost 20 seconds, which is concerning, but let's see how we can reduce it.

Controlling the Docker Compose lifecycle

If you stop the application, you will realize the Docker container of the database is not running anymore; this is because Spring Boot also destroys it.

The typical behavior when working locally will be to not stop the Docker container, which can be done by setting the value of the property spring.docker.compose.lifecycle-management to start-only. The other possible values are: "none" and "start-and-stop" which is the default.

Update the application.properties file to add the line below:


spring.docker.compose.lifecycle-management=start-only

Re-run the application, send a few requests to the API, and stop it; run docker ps to verify the container status, you will see it is still up.

The database container is still up after stopping the application.

Re-run the Spring Boot application again; we can see that the startup time reduced to a standard Spring Boot application startup time.

The application starts faster because the database already running.

Supported Docker images

The Docker Compose integration for Spring Boot supports the Docker images for the following databases and services:

Database/Service Container's name Image's link
Cassandra cassandra Docker Hub
Elasticsearch elasticsearch Docker Hub
Oracle database gvenzl/oracle-xe Docker Hub
MariaDB mariadb Docker Hub
Microsoft SQL Server microsoft-mssql-server Docker Hub
MySQL mysql Docker Hub
PostgreSQL postgres Docker Hub
MongoDB mongo Docker Hub
RabbitMQ rabbitmq Docker Hub
Redis redis Docker Hub
Zipkin openzipkin/zipkin Docker Hub
💡
The container's name is required because Spring Boot uses it to instantiate the service connection instance that will establish the connection to the database running on Docker. Read more about the Service connection.

Using a custom Docker image

If you are using a custom Docker image of the service listed earlier, you can use it in the Docker compose file with the condition to declare the label org.springframework.boot.service-connection and set the value to the base image name.

Deploy a Spring Boot application with Docker and Nginx Reverse Proxy
In this post, we will see how to deploy a Spring Boot application packaged with Docker, configure a reverse proxy with Nginx, and finally secure it with Lets Encrypt.

Example: if you use a custom image of MySQL, the value of the label org.springframework.boot.service-connection will be mysql.

The Docker compose file will look like this:


services:
  mysql:
    container_name: mysql
    image: tericcabrel/mysql:1.5
    restart: unless-stopped
    volumes:
      - "./db-data:/var/lib/mysql"
    ports:
      - 3307:3306
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - MYSQL_DATABASE=taskdb
    labels:
      org.springframework.boot.service-connection: mysql
      

Wrap up

Integrating Docker Compose with Spring Boot eases the experience of developing applications locally. Here are the main steps to make it work:

  • Declare the Docker compose with the supported images you want to run.
  • Install the Maven dependency for the Docker Compose integration.
  • Configure the Docker Compose lifecycle.
  • Start building your application locally.

You can use a custom Docker image and define some integration-related properties in the Spring Boot configuration file.

Read the documentation to see what you can do more with this integration.

You can find the code source on the GitHub repository.

Follow me on Twitter or subscribe to my newsletter to avoid missing the upcoming posts and the tips and tricks I occasionally share.