Docker compose wait for database service initialisation

13,075

Use the healthcheck feature of docker-compose (https://docs.docker.com/compose/compose-file/#healthcheck). Something like this:

services:
  demo-mysql:
    image: demo-mysql
    build: ./demo-mysql
    volumes:
      - /mnt/data/mysql-data:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=demo
      - MYSQL_PASSWORD=root
    healthcheck:
      test: ["CMD-SHELL", 'mysqladmin ping']
      interval: 10s
      timeout: 2s
      retries: 10

The depending containers will not start until the demo-mysql container is healthy

Share:
13,075
greenPadawan
Author by

greenPadawan

An engineer who seeks a challenging and unique assignment that provides me an opportunity to showcase my technical knowledge as well as provides me an opportunity to learn.

Updated on June 16, 2022

Comments

  • greenPadawan
    greenPadawan almost 2 years

    I have a spring boot project which I'd like to containerize using docker. I have a couple of spring boot applications which connect to same MySql server.

    My spring applications requires the database to be completely setup (i.e. all the tables to be created and some data to be inserted in some of the tables) in order to start.

    I am using Docker version 18.09.0 and docker-compose version 1.23.1 and ubuntu 16.04 LTS


    I have two files create.sql and insert.sql, which I use to initialise the database to be used by the application.

    I create the images using the command docker-compose.yml and it runs successfully and creates the images.

    I have the following questions.

    1. I assume when using docker-compose, a container starts as soon as all its dependent containers have started. Is there a way to wait for the mysql server to be up and ready to accept connections, before my API container gets started?

    2. If I chose to create containers separately for the applications and mysql, and not use docker-compose, how do I make sure that my applications connect to the mysql container?

    3. Is there any other tool which might help me achieve this?

    Note: I have tried to use docker inspect <container_id> to find the the IpAddress for the mysql container and use it to connect, but it doesn't work as well.


    The following are the files I am using to create images.

    docker-compose.yml file.

    version: '3'
    
    services:
      demo-mysql:
        image: demo-mysql
        build: ./demo-mysql
        volumes:
          - /mnt/data/mysql-data:/var/lib/mysql
        ports:
          - 3306:3306
        environment:
          - MYSQL_ROOT_PASSWORD=root
          - MYSQL_DATABASE=demo
          - MYSQL_PASSWORD=root
    
      demo-api:
        image: demo-api-1.0
        build: ./api
        depends_on:
          - demo-mysql
        ports:
          - 8080:8080
        environment:
          - DATABASE_HOST=demo-mysql
          - DATABASE_USER=root
          - DATABASE_PASSWORD=root
          - DATABASE_NAME=demo
          - DATABASE_PORT=3306
    
      demo1-app:
        image: demo1-app-1.0
        build: ./demo1
        depends_on:
          - demo-mysql
        ports:
          - 8090:8090
        environment:
          - DATABASE_HOST=demo-mysql
          - DATABASE_USER=root
          - DATABASE_PASSWORD=root
          - DATABASE_NAME=demo
          - DATABASE_PORT=3306
    

    The following is the Dockerfile for the spring boot project

    FROM java:8
    
    VOLUME /tmp
    
    ARG DATA_PATH=/src/main/resources
    ARG APP_PORT=8080
    
    EXPOSE ${APP_PORT}
    
    ADD /build/libs/demo-api.jar demo-api.jar
    
    ENTRYPOINT ["java","-jar","demo-api.jar"]
    

    The following is the Dockerfile I used to create my mysql image

    FROM mysql:5.7
    
    ENV MYSQL_DATABASE=demo \
        MYSQL_USER=root \
        MYSQL_ROOT_PASSWORD=root
    
    ADD ./1.0/create.sql /docker-entrypoint-initdb.d
    ADD ./1.0/insert.sql /docker-entrypoint-initdb.d
    
    EXPOSE 3306
    
  • Simonluca Landi
    Simonluca Landi over 5 years
    @greenPadawan: you are right, need to use "mysqladmin ping" for the healthcheck.
  • George Marin
    George Marin over 4 years
    health checks are no longer helping, condition on depends_on has been removed in docker 3, so even if you add your spring boot application to depend on the database, it will wait for it to run, not be ready.
  • arkhein
    arkhein almost 4 years
    @GeorgeMarin: right, the current supported way: docs.docker.com/compose/startup-order
  • pegasuspect
    pegasuspect over 3 years
    Please update the answer as this is no longer working. See the comment above.
  • Skraloupak
    Skraloupak almost 3 years
    Hello, i can recommend you to use /usr/bin/mysql --user=root --password=root --execute "SHOW DATABASE;" in healthcheck script instead of mysqladmin ping. This wait for real initialization.