Docker Compose中无restart_policy字段,真正实现健康驱动自愈需组合restart字段、healthcheck和depends_on的service_healthy条件;on-failure:5适用于无状态服务,unless-stopped适合守护进程,always慎用,且健康检查必须基于真实业务端点防“假活”。

Compose 的 restart_policy 本身并不存在——Docker Compose 中控制容器重启行为的是 restart 字段,而真正实现“按健康状态触发重启”的闭环自愈,必须结合 healthcheck 和 depends_on 的扩展条件(如 service_healthy),再配合 restart 策略共同生效。
restart 字段选型要匹配服务生命周期
不同策略响应逻辑差异大,选错会掩盖故障或引发雪崩:
- on-failure:5:适合 Web API、Job 类无状态服务。只在进程非零退出时重启,最多 5 次,避免死循环;对 OOM 杀死、信号终止不响应,更安全
-
unless-stopped:推荐用于 Nginx、Redis、RabbitMQ 等长期守护进程。宿主机重启后自动拉起,但
docker stop后不再启动,运维可控 - always 要慎用:手动停止后立即重启,调试困难;OOM 后反复拉起可能加剧资源争抢
- no:适用于数据迁移、一致性校验等关键一次性任务,禁止自动恢复
健康检查必须穿透到业务层
仅靠进程存活(PID 1 是否运行)无法识别“假活”:Node.js 卡死、Java 应用线程阻塞、端口监听但拒绝请求——这些情况下 on-failure 完全失效。
在 Dockerfile 中定义真实探针:
HEALTHCHECK \ --interval=20s \ --timeout=3s \ --start-period=40s \ --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1
-
--start-period=40s:给冷启动留足时间,避免刚起就误判为 unhealthy -
/health必须返回 HTTP 200 + JSON{"status":"ok"},不能是空响应或仅检测端口连通性 - 数据库类服务建议用原生工具:PostgreSQL 用
pg_isready,MySQL 用mysqladmin ping
依赖就绪 ≠ 容器启动,要用 service_healthy 控制启动顺序
depends_on 默认只等容器状态为 running,不等应用就绪。若前置服务(如 DB)尚未完成初始化,下游服务连接失败退出,可能触发无限重启循环。
正确写法(Compose v2.1+ 支持):
services:
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
api:
build: .
depends_on:
db:
condition: service_healthy
- 只有当
db容器通过全部健康检查,才启动api - 避免因“容器已启、服务未备”导致的级联失败
- 该机制不替代应用内的重试逻辑,而是降低启动阶段失败概率
让健康状态真正驱动重启:Compose 不自动重启 unhealthy 容器
Docker 引擎自身不会因为容器变 unhealthy 就重启它——这是常见误解。必须由编排层联动:
- 在
docker-compose.yml中显式配置:restart: on-failure或restart: unless-stopped - 同时确保
healthcheck已正确定义,且应用端点真实反映业务可用性 - 当健康检查连续失败(如
retries=3)后容器状态变为unhealthy,Docker 引擎会按 restart 策略判定是否重启——on-failure不响应 unhealthy 状态,unless-stopped和always也不响应;真正起作用的是 Compose 的restart_policy扩展字段(仅限 Swarm 或 Kubernetes) - 实际生产中,推荐使用
restart: on-failure+ 健康检查 + 应用内建重试,形成三层防护
不复杂但容易忽略。


















