Friday, August 31, 2018

Docker-compose check if mysql connection is ready

Leave a Comment

I am trying to make sure that my app container does not run migrations / start until the db container is started and READY TO accept connections.

So I decided to use the healthcheck and depends on option in docker compose file v2.

In the app, I have the following

app:     ...     depends_on:       db:       condition: service_healthy 

The db on the other hand has the following healthcheck

db:   ...   healthcheck:     test: TEST_GOES_HERE     timeout: 20s     retries: 10 

I have tried a couple of approaches like :

  1. making sure the db DIR is created test: ["CMD", "test -f var/lib/mysql/db"]
  2. Getting the mysql version: test: ["CMD", "echo 'SELECT version();'| mysql"]
  3. Ping the admin (marks the db container as healthy but does not seem to be a valid test) test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]

Does anyone have a solution to this?

4 Answers

Answers 1

version: "2.1" services:     api:         build: .         container_name: api         ports:             - "8080:8080"         depends_on:             db:                 condition: service_healthy     db:         container_name: db         image: mysql         ports:             - "3306"         environment:             MYSQL_ALLOW_EMPTY_PASSWORD: "yes"             MYSQL_USER: "user"             MYSQL_PASSWORD: "password"             MYSQL_DATABASE: "database"         healthcheck:             test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]             timeout: 20s             retries: 10 

The api container will not start until the db container is healthy (basically until mysqladmin is up and accepting connections.)

Answers 2

If you can change the container to wait for mysql to be ready do it.

If you don't have the control of the container that you want to connect the database to, you can try to wait for the specific port.

For that purpose, I'm using a small script to wait for a specific port exposed by another container.

In this example, myserver will wait for port 3306 of mydb container to be reachable.

# Your database mydb:   image: mysql   ports:     - "3306:3306"   volumes:     - yourDataDir:/var/lib/mysql  # Your server myserver:   image: myserver   ports:     - "....:...."   entrypoint: ./wait-for-it.sh mydb:3306 -- ./yourEntryPoint.sh 

You can find the script wait-for-it documentation here

Answers 3

I modified the docker-compose.yml as per the following example and it worked.

  mysql:     image: mysql:5.6     ports:       - "3306:3306"     volumes:              # Preload files for data       - ../schemaAndSeedData:/docker-entrypoint-initdb.d     environment:       MYSQL_ROOT_PASSWORD: rootPass       MYSQL_DATABASE: DefaultDB       MYSQL_USER: usr       MYSQL_PASSWORD: usr     healthcheck:       test:  mysql --user=root --password=rootPass -e 'Design your own check script ' LastSchema 

In my case ../schemaAndSeedData contains multiple schema and data seeding sql files. Design your own check script can be similar to following select * from LastSchema.LastDBInsert.

While web dependent container code was

depends_on:   mysql:     condition: service_healthy 

Answers 4

Hi for a simple healthcheck, I used:

/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\" 

Basically it runs a simple mysql command SHOW DATABASES; using as an example the user root with the password rootpasswd in the database.

If the command succeed the db is up and ready so the healthcheck path. You can use interval so it tests at interval.

Removing the other field for visibility, here is what it would look like in your docker-compose.yaml.

version: '2.1'    services:     db:       ...       healthcheck:         test: "/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\""         interval: 2s         timeout: 20s         retries: 10       app:        ...        depends_on:          db:          condition: service_healthy 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment