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 即可编排出「等依赖就绪再启动」的可靠依赖链。

笔记加载中…