How do I know when my docker mysql container is up

2019-01-08 18:23发布

I am deploying a few different docker containers, mysql being the first one. I want to run scripts as soon as database is up and proceed to building other containers. The script has been failing because it was trying to run when the entrypoint script, which sets up mysql (from this official mysql container), was still running.

sudo docker run --name mysql -e MYSQL_ROOT_PASSWORD=MY_ROOT_PASS -p 3306:3306 -d mysql
[..] wait for mysql to be ready [..]
mysql -h 127.0.0.1 -P 3306 -u root --password=MY_ROOT_PASS < MY_SQL_SCRIPT.sql

Is there a way to wait for a signal of an entrypoiny mysql setup script finishing inside the docker container? Bash sleep seems like a suboptimal solution.

EDIT: Went for a bash script like this. Not the most elegant and kinda brute force but works like a charm. Maybe someone will find that useful.

OUTPUT="Can't connect"
while [[ $OUTPUT == *"Can't connect"* ]]
do
    OUTPUT=$(mysql -h $APP_IP -P :$APP_PORT -u yyy --password=xxx <       ./my_script.sql 2>&1)
done

11条回答
相关推荐>>
2楼-- · 2019-01-08 19:04

This was more or less mentioned in comments to other answers, but I think it deserves it's own entry.

First of all you can run your container in the following manner:

docker run --name mysql --health-cmd='mysqladmin ping --silent' -d mysql

There is also an equivalent in the Dockerfile.

With that command your docker ps and docker inspect will show you health status of your container. For mysql in particular this method has the advantage of mysqladmin being available inside the container, so you do not need to install it on the docker host.

Then you can simply loop in a bash script to wait on the status to become healthy. The following bash script is created by Dennis.

function getContainerHealth {
  docker inspect --format "{{json .State.Health.Status }}" $1
}

function waitContainer {
  while STATUS=$(getContainerHealth $1); [ $STATUS != "\"healthy\"" ]; do 
    if [ $STATUS == "\"unhealthy\"" ]; then
      echo "Failed!"
      exit -1
    fi
    printf .
    lf=$'\n'
    sleep 1
  done
  printf "$lf"
}

Now you can do this in your script:

waitContainer mysql

and your script will wait until the container is up and running. The script will exit if the container becomes unhealthy, which is possible, if for example docker host is out of memory, so that the mysql cannot allocate enough of it for itself.

查看更多
何必那么认真
3楼-- · 2019-01-08 19:06

On your ENTRYPOINT script, you have to check if you have a valid MySQL connection or not.

This solution does not require you to install a MySQL Client on the container and while running the container with php:7.0-fpm running nc was not an option, because it had to be installed as well. Also, checking if the port is open does not necessarily mean that the service is running and exposed correctly. [more of this]

So in this solution, I will show you how to run a PHP script to check if a MySQL Container is able to take connection. If you want to know why I think this is a better approach check my comment here.

File entrypoint.sh

#!/bin/bash
cat << EOF > /tmp/wait_for_mysql.php
<?php
\$connected = false;
while(!\$connected) {
    try{
        \$dbh = new pdo( 
            'mysql:host=mysql:3306;dbname=db_name', 'db_user', 'db_pass',
            array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
        );
        \$connected = true;
    }
    catch(PDOException \$ex){
        error_log("Could not connect to MySQL");
        error_log(\$ex->getMessage());
        error_log("Waiting for MySQL Connection.");
        sleep(5);
    }
}
EOF
php /tmp/wait_for_mysql.php
# Rest of entry point bootstrapping

By running this, you are essentially blocking any bootstrapping logic of your container UNTIL you have a valid MySQL Connection.

查看更多
Juvenile、少年°
4楼-- · 2019-01-08 19:07

This little bash loop waits for mysql to be open, shouldn't require any extra packages to be installed:

until nc -z -v -w30 $CFG_MYSQL_HOST 3306
do
  echo "Waiting for database connection..."
  # wait for 5 seconds before check again
  sleep 5
done
查看更多
别忘想泡老子
5楼-- · 2019-01-08 19:07

The following health-check works for all my mysql containers:

db:
    image: mysql:5.7.16
    healthcheck:
      test: ["CMD-SHELL", 'mysql --database=$$MYSQL_DATABASE --password=$$MYSQL_ROOT_PASSWORD --execute="SELECT count(table_name) > 0 FROM information_schema.tables;" --skip-column-names -B']
      interval: 30s
      timeout: 10s
      retries: 4
    extends:
        file: docker-compose-common-config.yml
        service: common_service
查看更多
成全新的幸福
6楼-- · 2019-01-08 19:10

https://github.com/docker-library/mysql/blob/master/5.7/docker-entrypoint.sh docker-entrypoint.sh doesn't support merging customized .sql yet.

I think you can modify docker-entrypoint.sh to merge your sql so it can be executed once mysql instance is ready.

查看更多
登录 后发表回答