本文主要介绍 Docker 的容器重启策略(docker run --restart / Compose restart):各策略含义、退避行为、与 --rm 的互斥关系,以及运维上如何查看重启次数与适用场景。
内容整理自 Docker run reference:Restart policies,并结合常见部署习惯说明选用方式。具体行为以当前 Docker Engine 版本文档为准。
背景说明
容器进程退出后是否由 dockerd 拉起、守护进程重启后是否自动启动容器,由重启策略控制。策略写在容器配置里,可在 docker run、docker update 或 Compose/编排清单中声明。
策略生效时,docker ps 中容器状态多为 Up 或 Restarting;也可用 docker events 观察重启事件。
策略一览
| 策略 | 行为 |
|---|---|
no | 退出后不自动重启。默认值。 |
on-failure[:max-retries] | 仅在容器以非 0 状态退出时重启;可选限制最大重启次数。 |
always | 无论退出码如何都重启;且 dockerd 启动时会拉起该容器(不论之前是否被 stop,语义见下表对比)。 |
unless-stopped | 与 always 类似会自动重启,但若在 dockerd 停止前容器已被手动 stop,则 daemon 再启动时不会自动拉起。 |
说明(工程上常混用的点):
always:适合“机器重启后也要起来”的常驻服务;手动docker stop后,若再重启 Docker 服务,容器仍会被拉起。unless-stopped:同样适合常驻服务,但尊重“我主动停过”的状态,维护窗口更直观。on-failure:适合任务型/允许 0 正常退出的进程;成功退出(0)不会空转重启。no:调试、一次性任务、或由 systemd/K8s 等上层负责生命周期时使用。
退避与成功判定
为避免重启风暴,daemon 在连续重启之间加入指数退避:从 100ms 起,每次加倍(100 → 200 → 400 → …),直到:
- 命中
on-failure的最大次数,或 - 对容器执行了
docker stop/docker rm -f
若某次启动后容器持续运行至少约 10 秒,退避延迟会重置为 100ms。因此“起来又秒退”会拉长间隔,看起来像“重启变慢”,属于保护行为。
配置示例
docker run
# 总是重启
docker run -d --name redis --restart=always redis:latest
# 非 0 退出才重启,最多连续尝试 10 次
docker run -d --name redis --restart=on-failure:10 redis:latest
修改已有容器
docker update --restart=unless-stopped <container>
与 –rm 互斥
--restart 与 --rm 不能同时使用。重启场景下容器实例要保留;--rm 则在退出时删除容器,语义冲突,daemon 会直接报错。
Compose 示意
services:
app:
image: <image>
restart: unless-stopped
观测与验证
查看重启次数:
docker inspect -f '{{ .RestartCount }}' <container>
查看最近一次启动时间:
docker inspect -f '{{ .State.StartedAt }}' <container>
查看当前策略:
docker inspect -f '{{ .HostConfig.RestartPolicy.Name }} {{ .HostConfig.RestartPolicy.MaximumRetryCount }}' <container>
验证思路(按策略自测,勿在生产乱杀进程):
- 对
always/unless-stopped容器docker stop再docker start,确认可手动拉起。 - 模拟非 0 退出(例如错误入口命令),观察
RestartCount是否增加、on-failure:N是否在 N 次后停止。 - 重启 Docker 服务后,对比
always与unless-stopped(后者在 stop 过的容器上不应自动 Up)。
示例输出中的数字与时间为文档常见示意,以本机 inspect 为准:
# RestartCount 示例
2
# StartedAt 示例
2015-03-04T23:47:07.691840179Z
与 docker run 退出码的关系
docker run 前台退出码可帮助区分失败阶段(摘自官方说明):
| 退出码 | 含义 |
|---|---|
| 125 | Docker daemon / 客户端自身错误(如非法 flag) |
| 126 | 容器内命令无法执行(权限等) |
| 127 | 容器内命令不存在 |
| 其它 | 一般为容器内进程的退出码 |
docker run --foo busybox; echo $?
# 非法参数 → 常为 125
docker run busybox /bin/sh -c 'exit 3'; echo $?
# 进程 exit 3 → 输出 3
重启策略看的是容器退出后的守护行为,与上述前台 docker run 退出码 complementary:编排排障时两者都要看。
选用建议
| 场景 | 更合适的策略 |
|---|---|
| Web/Redis 等常驻服务,希望开机自启 | unless-stopped(常用)或 always |
| 批处理,0 表示成功结束 | on-failure 或 no |
| 本地调试 | no |
| 已由 Kubernetes/Systemd 管生命周期 | 通常 no,避免双重拉起 |
Swarm/Compose/K8s 还有各自的重启与健康检查模型,不要假设与单机 --restart 完全一致。
注意事项
- 应用自身应尽量可重入;依赖“重启凑活”会掩盖配置错误。
- 连续崩溃时关注退避导致的间隔变长,结合日志查根因。
MaximumRetryCount仅对on-failure有意义。- 文档链接与语义随 Docker 版本可能微调,升级 Engine 后核对官方 run reference。