9

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

2 Answers 2

5

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

Sign up to request clarification or add additional context in comments.

8 Comments

@greenPadawan: you are right, need to use "mysqladmin ping" for the healthcheck.
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.
@GeorgeMarin: right, the current supported way: docs.docker.com/compose/startup-order
@Skraloupak: it's SHOW DATABASES and had to use "CMD" instead of "CMD-SHELL" to make it work but although I see the health check succeeds it doesn't seem to make docker wait for mysql to be healthy before it starts further containers
In current docker versions you must specifiy 'condition: service_healthy' in order for that to work. See my complete answer.
|
1

In the current Docker version 24, depends_on by default only waits until the container it depends on is started, which ignores the health check. If you need to wait for it to become "healthy", you need to use the long syntax and specify the condition as service_healthy or in my case when using jwilder/dockerize service_completed_successfully.

See https://docs.docker.com/compose/compose-file/05-services/#long-syntax-1

services:
   mysql:      
      image: mysql:8.0.34
     environment:
        MYSQL_ROOT_PASSWORD: mypassword
        MYSQL_DATABASE: mydb
     ports:
        - 3306:3306      
     healthcheck:
        test: ["CMD", "/usr/bin/mysql", "--user=root",  "--password=mypassword", "--execute", "SHOW DATABASES;"]
     interval: 2s
     timeout: 2s
     retries: 10

   check-db-started:
      image: jwilder/dockerize:0.6.1          
      depends_on:
         - mysql          
      command: 'dockerize -wait=tcp://mysql:3306 -timeout 30s'

   springbootapp:
      image: myappimage
      environment:
         MYSQL_HOST: mysql
      ports:
         - 8080:8080
      depends_on:
         check-db-started:
            condition: service_completed_successfully

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.