Search code examples
mysqlspring-bootdocker-compose

Containerized Spring boot application is unable to connect to database within container


I seem to be encountering an error within an application that I have created in changing it to be ran via docker.

I want to be able to stat the application from running docker compose so I created a compose file with the following:

version: '3.9'
services:
  mysql:
    container_name: dbcontainer
    image: mysql
    environment:
      MYSQL_DATABASE: 
      MYSQL_USER: amazing05
      MYSQL_PASSWORD: amazing05
      MYSQL_ROOT_PASSWORD: amazing05
    ports:
      - "3306:3306"
    volumes:
      - ./sql:/docker-entrypoint-initdb.d
    networks:
      - my_network
        
  springbootapplication:
    depends_on:
      - mysql
    build: .
    ports:
      - "8080:80"

    environment:
      MYSQL_CONTAINER: dbcontainer
      MYSQL_USER: amazing05
    networks:
      - my_network
    restart: on-failure
    
networks:
  my_network:
    driver: bridge 

Application properties

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql = true
spring.datasource.url=jdbc:mysql://${MYSQL_CONTAINER:localhost}:3306/mycontainerdb
spring.datasource.username=${MYSQL_USER:root}
spring.datasource.password=${MYSQL_USER:root}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

Before I run the compose command I do a maven install to generate the application jar as I created a DockerFile to be built.

Once the containers are spun up I am met with this error

springbootapplication-1  | com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
springbootapplication-1  | 
springbootapplication-1  | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

This means the spring boot application did not find the container to connect to, but if I am to comment out the spring boot application service and run manually it finds the container fine. Any help much appreciated

I have tried running the application through docker compose and produces the error above but when I run just the mysql container and run the spring boot application manually it finds it successfully.


Solution

  • Docker Compose's depends_on only ensures that the MySQL container starts before the Spring Boot application container. It does not ensure that MySQL is ready to accept connections. You need to add a wait mechanism to ensure that the Spring Boot application only starts after MySQL is fully up and ready.

    So you should add a Healthcheck to MySQL Service to ensure that is fully up and running before the Spring Boot application attempts to connect.

    version: '3.9'
    services:
      mysql:
        container_name: dbcontainer
        image: mysql
        environment:
          MYSQL_DATABASE: mycontainerdb
          MYSQL_USER: amazing05
          MYSQL_PASSWORD: amazing05
          MYSQL_ROOT_PASSWORD: amazing05
        ports:
          - "3306:3306"
        volumes:
          - ./sql:/docker-entrypoint-initdb.d
        networks:
          - my_network
        healthcheck:
          test: ["CMD", "mysqladmin ping -h localhost"]
          interval: 10s
          timeout: 5s
          retries: 3
      
      springbootapplication:
        depends_on:
          mysql:
            condition: service_healthy
        build: .
        ports:
          - "8080:80"
        environment:
          MYSQL_CONTAINER: dbcontainer
          MYSQL_USER: amazing05
          MYSQL_PASSWORD: amazing05
        networks:
          - my_network
        restart: on-failure
        
    networks:
      my_network:
        driver: bridge