Deploying a Spring Boot App and MySQL in Docker Containers

In this tutorial, you will learn how to deploy a Spring Boot application and a MySQL server in separate Docker containers. By the end of this tutorial, you will know how to run your Spring Boot application in one Docker container and your MySQL server in another Docker container and how to make them communicate with each other.

To learn more about Docker, please check other Docker tutorials for Beginners.

What You’ll Learn:

  1. How to create a Spring Boot application.
  2. How to setup MySQL server in a Docker container.
  3. How to setup the Spring Boot application in another Docker container.
  4. How to enable communication between the two Docker containers.

Prerequisites:

Before we start, you need to have these installed on your computer:

Creating our Spring Boot Application

First, let’s create our Spring Boot application using Spring Initializr. Open Spring Initializr in your browser. For the Project metadata, use these values:

  • Group: com.example
  • Artifact: dockerdemo
  • Packaging: Jar
  • Java: 11

Under Dependencies, select Spring Web, Spring Data JPA and MySQL Driver. Then, click on the Generate button to download the project. Unzip and open it in your IDE.

In the src/main/java/com.example.dockerdemo package, create a new Java class named UserEntity with these fields: firstName, lastName, email, password. Annotate this class with @Entity to make it a JPA entity and @Table(name = "users") to map it with the ‘users’ table in the MySQL database.

Next, create a UserRepository interface in the same package, which extends JpaRepository<UserEntity, Long>. This interface will provide us with basic CRUD operations for the UserEntity.

Finally, create a UserController class annotated with @RestController. Add a /users POST API endpoint which accepts user details in JSON format and stores it in the database using UserRepository.

Setting up MySQL Server in a Docker Container

The second step involves setting up our MySQL server in a Docker container. Normally, this would require a Dockerfile. However, we are going to use a more flexible approach, a docker-compose.yml file to define our MySQL service. This file allows us to manage multiple services more efficiently.

The docker-compose.yml file should be created in the root directory of your Spring Boot project, where your pom.xml file resides. This is crucial because Docker-compose works in the context of this directory, also known as the project root directory.

Here’s what you need to do:

Create a new file named docker-compose.yml in the root directory of your Spring Boot project and paste in the following content:

version: '3.1'
services:
  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: testdb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - 3306:3306
    volumes:
      - db_data:/var/lib/mysql
volumes:
  db_data: {}

This script will perform several actions. It will:

  1. Pull the MySQL 8.0 image from Docker Hub.
  2. Create a new MySQL server.
  3. Set the root password as ‘root’.
  4. Create a new database named ‘testdb’ along with a user named ‘user’ and a password ‘password’.
  5. Expose the MySQL server on port 3306.
  6. Persist the data on a Docker volume named ‘db_data’ to ensure data is not lost when the container stops.

Setting up Spring Boot Application in a Docker Container

To package our Spring Boot application inside a Docker container, we first need a Dockerfile. Create a new file named Dockerfile in the root directory of the project with the following content:

FROM openjdk:11
ADD target/dockerdemo-0.0.1-SNAPSHOT.jar dockerdemo.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "dockerdemo.jar"]

This Dockerfile does the following:

  • Uses openjdk:11 as the base image.
  • Adds the output jar file dockerdemo-0.0.1-SNAPSHOT.jar from the target directory to the Docker image and renames it to dockerdemo.jar.
  • Exposes port 8080.
  • Specifies the command to start our Spring Boot application.

Before building our Docker image, we need to package our application into a jar file. Open the terminal in the project root directory and execute: ./mvnw clean package.

Now, we can build our Docker image using: docker build -t dockerdemo .

Enabling Communication Between the Two Docker Containers

We’ve successfully setup our Spring Boot application and MySQL server in separate Docker containers. Now, we need to make them communicate with each other.

Go back to docker-compose.yml and add another service for our Spring Boot application:

version: '3.1'

services:

  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: testdb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - 3306:3306
    volumes:
      - db_data:/var/lib/mysql

  web:
    image: dockerdemo
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:8080
    depends_on:
      - db
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/testdb
      SPRING_DATASOURCE_USERNAME: user
      SPRING_DATASOURCE_PASSWORD: password
      SPRING_JPA_HIBERNATE_DDL_AUTO: update

volumes:
  db_data: {}

This file accomplishes the following:

  • Sets up a MySQL database in a Docker container, just like we did in Step 2. The MySQL server is exposed on port 3306, and the data is persisted on a Docker volume named ‘db_data’.
  • Sets up the Spring Boot application in another Docker container. It uses the Dockerfile in the current directory to build the Docker image for the Spring Boot application, and then runs the application, exposing it on port 8080.
  • The depends_on attribute ensures that the ‘db’ service (the MySQL server) starts before the ‘web’ service (the Spring Boot application).
  • Environment variables are set for the ‘web’ service to connect to the ‘db’ service. The SPRING_DATASOURCE_URL points to the ‘db’ service, and SPRING_DATASOURCE_USERNAME and SPRING_DATASOURCE_PASSWORD provide the credentials for connecting to the MySQL server.

With this setup, running docker-compose up in the terminal will start both services. The Spring Boot application will be accessible at localhost:8080 and it will be able to interact with the MySQL server running in a separate Docker container.

Congratulations! You have successfully deployed a Spring Boot application and a MySQL server in separate Docker containers and enabled communication between them.

Frequently Asked Questions

  1. Why should I use Docker-compose?
    Docker-compose is a tool that is used to define and manage multi-container Docker applications. It allows you to define your infrastructure, including application services, networks, and volumes, in a single file (docker-compose.yml), making it easier to manage and update your application as a whole.
  2. How can I ensure that my Spring Boot application can communicate with the MySQL container?
    In your Spring Boot application’s application.properties file, you need to set the spring.datasource.url property to point to the MySQL container. In a Docker Compose context, you can simply use the service name as the hostname, like so: jdbc:mysql://db:3306/testdb.
  3. How can I handle data persistence with MySQL in a Docker container?
    In the Docker Compose file, you can define a volume to persist the data from your MySQL container. This means that the data will be stored on the host machine and will survive the container being stopped and started again.
  4. Can I debug my Spring Boot application when it’s running in a Docker container?
    Yes, you can. By exposing the debug port in your Dockerfile and running the Spring Boot application in debug mode, you can connect your IDE to the application for debugging.
  5. Can I scale my Spring Boot application with Docker?
    Yes, with Docker Compose, you can scale your application by specifying the number of “replicas” of your application service you want to run. Combined with a load balancer, this can allow you to handle increased traffic to your application.