har*_*ren 53 mysql bash shell docker
我正在部署一些不同的docker容器,mysql是第一个.我想在数据库启动后立即运行脚本并继续构建其他容器.该脚本一直在失败,因为当设置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
Run Code Online (Sandbox Code Playgroud)
有没有办法等待在docker容器内完成入门的mysql安装脚本的信号?Bash睡眠似乎是次优解决方案.
编辑:去找这样的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
Run Code Online (Sandbox Code Playgroud)
fla*_*yst 49
您可以安装mysql-client软件包并使用mysqladmin来ping目标服务器.使用多个docker容器时很有用.结合sleep并创建一个简单的等待循环:
while ! mysqladmin ping -h"$DB_HOST" --silent; do
sleep 1
done
Run Code Online (Sandbox Code Playgroud)
小智 32
这个小的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
Run Code Online (Sandbox Code Playgroud)
And*_*ykh 24
在其他答案的评论中或多或少地提到了这一点,但我认为它应该是它自己的条目.
首先,您可以按以下方式运行容器:
docker run --name mysql --health-cmd='mysqladmin ping --silent' -d mysql
Run Code Online (Sandbox Code Playgroud)
Dockerfile中还有一个等价物.
与该命令你docker ps
,并docker inspect
会告诉你你的容器的健康状况.特别是对于mysql,此方法具有在容器内mysqladmin
可用的优点,因此您无需在docker主机上安装它.
然后你可以简单地循环一个bash脚本来等待状态变得健康.以下bash脚本由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"
}
Run Code Online (Sandbox Code Playgroud)
现在您可以在脚本中执行此操作:
waitContainer mysql
Run Code Online (Sandbox Code Playgroud)
并且您的脚本将一直等到容器启动并运行.如果容器变得不健康,脚本将退出,这是可能的,如果例如docker host内存不足,那么mysql无法为自己分配足够的内容.
Mih*_*iță 12
在所有 Linux 发行版上都可以找到使用curl 的一种衬垫:
while ! curl -o - db-host:3306; do sleep 1; done
Run Code Online (Sandbox Code Playgroud)
有时端口的问题是端口可能是打开的,但数据库还没有准备好.
其他解决方案要求你在主机上安装了mysql oa mysql客户端,但实际上你已经在Docker容器中安装了它,所以我更喜欢使用这样的东西:
while ! docker exec mysql mysqladmin --user=root --password=root --host "127.0.0.1" ping --silent &> /dev/null ; do
echo "Waiting for database connection..."
sleep 2
done
Run Code Online (Sandbox Code Playgroud)
以下运行状况检查适用于我的所有 mysql 容器:
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
Run Code Online (Sandbox Code Playgroud)
所以我不确定是否有人发布过这个。它看起来不像任何人,所以...... mysqladmin 中有一个命令具有等待功能,它处理连接测试,然后在内部重试并在完成后返回成功。
sudo docker run --name mysql -e MYSQL_ROOT_PASSWORD=MY_ROOT_PASS -p 3306:3306 -d mysql
mysqladmin ping -h 127.0.0.1 -u root --password=MY_ROOT_PASS --wait=30 && mysql -h 127.0.0.1 -P 3306 -u root --password=MY_ROOT_PASS < MY_SQL_SCRIPT.sql
Run Code Online (Sandbox Code Playgroud)
的重要的部分是mysqladmin ping -h 127.0.0.1 -u root --password=MY_ROOT_PASS --wait=30 -v
与--wait
作为标记等到连接成功和数为尝试重试的量。
理想情况下,您应该从 docker 容器内部运行该命令,但我不想过多地修改原始海报命令。
在我的 make 文件中用于初始化时
db.initialize: db.wait db.initialize
db.wait:
docker-compose exec -T db mysqladmin ping -u $(DATABASE_USERNAME) -p$(DATABASE_PASSWORD) --wait=30 --silent
db.initialize:
docker-compose exec -T db mysql -u $(DATABASE_USERNAME) -p$(DATABASE_PASSWORD) $(DATABASE_NAME) < dev/sql/base_instance.sql
Run Code Online (Sandbox Code Playgroud)
我发现使用这种mysqladmin ping
方法并不总是可靠的,尤其是当您要建立一个新的数据库时。在这种情况下,即使您能够ping通服务器,但如果仍在初始化用户/特权表,则可能无法连接。相反,我会执行以下操作:
while ! docker exec db-container mysql --user=foo --password=bar -e "SELECT 1" >/dev/null 2>&1; do
sleep 1
done
Run Code Online (Sandbox Code Playgroud)
到目前为止,我还没有遇到这种方法的任何问题。我看到VinGarcia在对其中一个mysqladmin ping
答案的评论中提出了类似的建议。
https://github.com/docker-library/mysql/blob/master/5.7/docker-entrypoint.sh docker-entrypoint.sh 尚不支持合并自定义.sql。
我认为你可以修改 docker-entrypoint.sh 来合并你的sql,这样一旦mysql实例准备好它就可以执行。
归档时间: |
|
查看次数: |
36981 次 |
最近记录: |