Docker 健康检查与重启策略
进程退出不等于服务不可用:进程活着但端口无响应同样是故障。本章讲如何用健康检查探测服务是否真的就绪,并用重启策略让守护进程自动拉起挂掉的容器。
重启策略 --restart
四种策略的触发条件差异如下表:
| 策略 | 自动重启条件 | 手动 docker stop 之后 |
|---|---|---|
| no(默认) | 不自动重启 | 保持停止 |
| on-failure[:次数] | 仅非 0 退出码,可限次数如 on-failure:3 | 保持停止 |
| unless-stopped | 任意退出都重启 | daemon 重启也不会再拉起 |
| always | 任意退出都重启 | 保持停止,但 daemon 重启时会重新拉起 |
docker run -d --restart unless-stopped --name app myapp
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' app
# 输出:unless-stopped
被 OOM 杀掉(退出码 137)也属非 0 退出,on-failure 同样会拉起;策略由守护进程执行,容器退出后几秒内自动重启。
Dockerfile 的 HEALTHCHECK
HEALTHCHECK 定义探测命令,间隔、超时、失败重试次数均可调;命令非零退出即认为本次不健康:
FROM nginx:1.27-alpine
HEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=10s \
CMD wget -q -O /dev/null http://127.0.0.1/ || exit 1
状态用 docker inspect 查看,依次经历 starting、healthy、unhealthy:
docker inspect --format '{{.State.Health.Status}}' web
# 输出:healthy
docker inspect --format '{{json .State.Health.Log}}' web # 最近几次检查明细
注意精简镜像常不带 curl,alpine/busybox 系用 wget 即可。
Compose 中的 healthcheck 与联动
compose 文件的 healthcheck 与 docker run 语义一致;test 既可用 JSON 数组 exec 形式,也可用 CMD-SHELL 走 shell:
services:
web:
image: myapp
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://127.0.0.1:8080/health || exit 1"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
编排联动:depends_on 配 condition: service_healthy 让下游等服务「健康」再启动:
services:
app:
image: myapp
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD"]
小结
重启策略解决「进程挂了自动拉」,健康检查解决「进程活着但不可用」;两者常配套使用,再加 depends_on condition 即可编排出「等依赖就绪再启动」的可靠依赖链。