如何知道我的docker mysql容器何时启动,mysql已准备好接受查询?

我正在部署一些不同的docker容器,mysql是第一个。 我想在数据库启动后立即运行脚本并继续构build其他容器。 该脚本一直失败,因为它试图运行时,设置MySQL(从这个官方的MySQL容器 )入口脚本,仍然在运行。

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 

是否有一种方法来等待docker容器内完成一个入口的mysql安装脚本的信号? 巴什睡眠似乎是一个不理想的解决scheme。

编辑:去这样的bash脚本。 不是最优雅和有点暴力,但作品像一个魅力。 也许有人会觉得有用。

 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 

您可以安装mysql-client软件包并使用mysqladmin来ping目标服务器。 使用多个docker集装箱时很有用。 结合睡眠并创build一个简单的等待循环:

 while ! mysqladmin ping -h"$DB_HOST" --silent; do sleep 1 done 

这个小小的bash循环等待mysql被打开,不应该要求安装任何额外的软件包:

 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 

这个或多或less在其他答案的评论中提到,但我认为它值得它自己的条目。

首先,您可以按照以下方式运行您的容器:

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

在Dockerfile中也有一个等价的。

通过该命令,您的docker psdocker inspectdocker inspect您的集装箱的健康状况。 对于mysql来说,这个方法具有mysqladmin 在容器内部可用的优点,所以你不需要在docker主机上安装它。

然后你可以简单地循环一个bash脚本来等待状态变得健康。 下面的bash脚本是由Dennis创build的。

 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" } 

现在你可以在你的脚本中做到这一点:

 waitContainer mysql 

你的脚本将一直等到容器启动并运行。 如果容器变得不健康,脚本将会退出,如果docker主机内存不足,这可能会导致mysql无法为自己分配足够的内存。

https://github.com/docker-library/mysql/blob/master/5.7/docker-entrypoint.sh docker-entrypoint.sh不支持合并自定义的.sql。

我想你可以修改docker-entrypoint.sh来合并你的sql,这样一旦mysql实例准备好就可以执行它。

当我的Django容器在启动后试图连接mysql容器时,我遇到了同样的问题。 我用vishnubob的wait-for.it.sh脚本解决了这个问题。 它是一个等待IP和主机准备就绪的shell脚本,然后继续。 以下是我用于应用程序的示例。

 ./wait-for-it.sh \ -h $(docker inspect --format '{{ .NetworkSettings.IPAddress }}' $MYSQL_CONTAINER_NAME) \ -p 3306 \ -t 90 

在那个脚本中,我要求mysql容器在端口3306(默认的mysql端口)中等待最长90秒(准备就绪后会正常运行),以及由我的MYSQL_CONTAINER_NAME的docker签名的主机。 脚本有更多的variables,但是mw与这三个工作。

在你的ENTRYPOINT脚本中,你必须检查你是否有一个有效的MySQL连接。

这个解决scheme并不要求你在容器上安装一个MySQL客户端,并且用php:7.0-fpm运行容器php:7.0-fpm运行nc php:7.0-fpm不是一个选项,因为它也必须被安装。 此外,检查端口是否打开并不一定意味着该服务正在运行并正确显示。 [更多]

所以在这个解决scheme中,我将向您展示如何运行PHP脚本来检查MySQL容器是否能够连接。 如果你想知道为什么我认为这是一个更好的方法检查我的评论在这里 。

文件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 

通过运行这个,你基本上阻止了你的容器的任何引导逻辑直到你有一个有效的MySQL连接。