Docker Compose 怎样按 restart 策略恢复服务
来源:17golang原创
时间:2026-10-19 22:00:15 129浏览 收藏
服务容器退出后没有按预期回来,很多时候不是 Docker Compose “失灵”,而是 restart 只对特定的退出场景生效。配置前先把服务、退出类型和人工停止动作分开看:正常退出是否要重启,异常退出是否允许重试,以及运维人员手动停止后是否仍希望它自动回来。
官方地址:https://docs.docker.com/compose/
最小判断规则是:短任务或一次性任务通常用no;只想覆盖异常退出时用on-failure;需要持续拉起服务时再考虑always或unless-stopped。手动停止是单独的边界,不能只看退出码。
restart写在目标 service 下,不是写在顶层。on-failure:3只针对非零退出,并限制失败重试次数。- 修改
compose.yaml后要重新执行docker compose up -d;单独执行docker compose restart不会把新的配置变成容器参数。
从项目目录定位要调整的服务
我处理这类问题时,第一步不是马上把策略改成 always,而是先确认 Compose 项目的入口和服务名。操作路径可以固定为“项目目录 → compose.yaml → services → 目标服务 → restart 字段”。如果项目同时有前端、API 和一次性迁移服务,重启策略通常不应该全部相同。
# 在包含 compose.yaml 的项目目录中列出服务名 docker compose config --services # 查看当前项目中已创建的容器,包括已经退出的容器 docker compose ps -a
第一个命令帮助你确认要修改的 service key,第二个命令帮助你把“服务配置”与“当前容器状态”对应起来。这里看到的退出状态只是排查线索,真正的策略仍要回到配置文件中判断。

在服务配置中选择 restart 策略
打开 compose.yaml 后,把字段放在具体服务下面。下面的示例把 Web 服务设置为“除非被明确停止,否则保持恢复”,并把一次性迁移任务设为不自动重跑:
services:
web:
image: example/web:1.0
restart: unless-stopped # 服务异常退出后恢复,人工停止后不主动拉起
migrate:
image: example/web:1.0
command: ["./app", "migrate"] # 迁移任务完成后退出,不应被无限重启
restart: "no" # 一次性任务使用默认策略,避免重复执行
Compose 服务级别的常用值可以这样理解:
| 值 | 主要行为 | 适合场景 |
|---|---|---|
no | 不自动重启 | 迁移、备份、批处理等一次性任务 |
always | 无论退出码如何都尝试恢复,直到容器被移除 | 需要持续存活且正常退出也要拉起的服务 |
on-failure | 只在非零退出时重启 | 把正常完成视为结束、把异常退出视为故障的任务 |
on-failure:3 | 非零退出时最多尝试有限次数 | 允许短暂恢复,但不希望无限重试的服务 |
unless-stopped | 通常持续恢复,但明确停止后保持停止 | 长期服务和需要人工停机窗口的项目 |
选择字段时,优先问“正常退出是不是成功”。如果是成功完成就应该停下来的任务,不要为了“看起来可靠”统一使用 always;否则迁移或批处理可能被重复执行。
对照退出码和手动停止边界
真正容易混淆的是三个相似场景:进程以退出码 0 结束、以非零退出码结束,以及管理员通过 Compose 或 Docker 主动停止容器。策略的选择可以按下面的判断表落地:
| 事件 | no | on-failure | always/unless-stopped |
|---|---|---|---|
| 退出码为 0 | 不恢复 | 不恢复 | 按策略恢复,除非处于明确停止边界 |
| 退出码非 0 | 不恢复 | 恢复并按次数限制 | 恢复 |
| 人工执行 stop | 保持停止 | 保持停止,直到重新启动 | 明确停止后保持停止;守护进程或容器被重新启动时再按规则判断 |
因此,看到容器是 Exited (0) 时,先别急着认为是故障;它可能只是一次性命令正常完成。反过来,看到非零退出,也不能只把重试次数拉到很大,应该结合日志确认是不是配置错误、依赖不可用或应用自身反复崩溃。

保存配置并重新应用项目
编辑器中保存 compose.yaml 后,回到项目目录执行 up,让 Compose 按新的服务定义重新协调容器:
# 重新应用服务定义,并让服务在后台运行 docker compose up -d # 查看服务当前状态和容器是否仍在退出 docker compose ps -a # 查看最近日志,确认退出原因而不是只看重启次数 docker compose logs --tail=50 web
界面或命令输出中,成功的确认点应该是:目标 service 使用了新的配置,容器状态与预期一致,日志能够解释进程为何退出。若只是执行 docker compose restart,它的作用是重启现有服务容器,配置文件中新增的环境变量或其他创建参数不会因此自动更新;需要用 up 重新应用定义。
看似不生效时先排除三个误区
误区一:把 restart 当成健康检查。它主要处理容器终止后的恢复,不等于应用已经能对外提供服务。应用需要依赖数据库或其他服务时,还要单独设计健康检查和依赖启动条件。
误区二:把正常退出当成崩溃。迁移、导入、备份等任务完成后退出码为 0 很正常。给它们设置 always,可能会让任务重复执行。
误区三:人工停止后期待它立刻回来。Docker 官方说明中,手动停止会让自动重启策略暂时失效,直到守护进程重启或容器被手动重新启动。停机维护时应把这个边界告诉值班人员,否则“服务没恢复”可能其实是人为动作的预期结果。
常见问题
on-failure:3 中的 3 是时间还是次数?
这里表示失败重试次数上限,不是等待时间。它只针对非零退出;若任务以 0 结束,通常不会因为这个策略再次启动。
改完 restart 后为什么感觉没有变化?
先确认字段缩进在目标 service 下,再使用 docker compose up -d 重新应用。只运行 docker compose restart 只会重启现有容器,不会把所有配置变更转换成新的容器创建参数。
结语
Docker Compose 的 restart 选择应该从任务生命周期出发:一次性任务先考虑 no,异常才算失败的任务用 on-failure,长期服务再在 always 与 unless-stopped 之间判断人工停机需求。把 service、退出码和手动停止分开核对,再用 up 重新应用配置,通常就能解释大多数“容器为什么没按预期恢复”的问题。
-
160 收藏
-
105 收藏
-
420 收藏
-
276 收藏
-
175 收藏
-
496 收藏
-
465 收藏
-
383 收藏
-
365 收藏
-
170 收藏
-
384 收藏
-
461 收藏
-
224 收藏
-
459 收藏
-
429 收藏
-
217 收藏
-
101 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习