我有一个
docker-compose.yml
,提供以下服务:
services:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
environment:
- MYSQL_USER=cct1
- MYSQL_DATABASE=cct1
- MYSQL_PORT=3306
- MYSQL_PASSWORD_FILE=/run/secrets/mysql-password
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql-password
healthcheck:
test:
[
"CMD-SHELL",
# "sh",
# "-c",
"mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$(cat /run/secrets/mysql-password)"
]
start_period: 5s
interval: 3s
timeout: 5s
retries: 6
secrets:
- mysql-password
secrets:
mysql-password:
file: ./mysql_pwd.secret
当我运行
docker stack deploy stack-name
时,db
服务失败 (Received SHUTDOWN from user root
),原因在运行状况检查中。我已经找到了一个可行的解决方案,但我缺少逻辑:似乎 mysqladmin ping ...
命令必须使用 sh -c
: 在 shell 内运行
[
"CMD-SHELL",
"sh",
"-c",
"mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$(cat /run/secrets/mysql-password)"
]
而且它有效。
文档非常清楚
CMD-SHELL
的作用:
使用
使用容器的默认 shell 运行配置为字符串的命令(对于 Linux 为CMD-SHELL
)/bin/sh
那么为什么我需要额外的外壳呢?其他几种替代方案也会导致部署失败,例如这个:
[
"CMD",
"sh",
"-c",
"mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$(cat /run/secrets/mysql-password)"
]
为什么?第二个外壳似乎是强制性的,但我无法理解原因。我还检查了 MySQL Docker 映像,但
SHELL
没有被覆盖。
我认为你可以稍微简化一下。如果您只是 ping 数据库,您可能不需要指定凭据。
services:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
environment:
- MYSQL_USER=cct1
- MYSQL_DATABASE=cct1
- MYSQL_PORT=3306
- MYSQL_ROOT_PASSWORD=secret
healthcheck:
test: [ "CMD", "mysqladmin", "ping" ]
start_period: 5s
interval: 3s
timeout: 5s
retries: 6
使用硬编码密码而不是秘密。但您应该能够
docker-compose up
,然后验证容器是否标记为健康。
或者,您可以像这样指定健康检查:
healthcheck:
test: [ "CMD-SHELL", "mysqladmin ping" ]
start_period: 5s
interval: 3s
timeout: 5s
retries: 6
区别(据我所知!)是
CMD-SHELL
将在 shell 中运行命令,而 CMD
将在没有 shell 的情况下运行命令。后者的开销较小,如果您经常运行运行状况检查,这可能会很重要。