登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  软件教程

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,第二个命令帮助你把“服务配置”与“当前容器状态”对应起来。这里看到的退出状态只是排查线索,真正的策略仍要回到配置文件中判断。

原创界面说明图:从项目目录进入 compose.yaml 的 services 并定位 web 服务的 restart 字段
图1:Docker Compose 服务配置入口的原创界面说明图,展示项目文件、服务节点和 restart 字段的对应关系,不是真实截图。

在服务配置中选择 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 主动停止容器。策略的选择可以按下面的判断表落地:

事件noon-failurealways/unless-stopped
退出码为 0不恢复不恢复按策略恢复,除非处于明确停止边界
退出码非 0不恢复恢复并按次数限制恢复
人工执行 stop保持停止保持停止,直到重新启动明确停止后保持停止;守护进程或容器被重新启动时再按规则判断

因此,看到容器是 Exited (0) 时,先别急着认为是故障;它可能只是一次性命令正常完成。反过来,看到非零退出,也不能只把重试次数拉到很大,应该结合日志确认是不是配置错误、依赖不可用或应用自身反复崩溃。

原创界面说明图:Docker Compose restart 策略对照退出码 0、非零退出码和手动停止后的恢复判断
图2:restart 策略与退出状态的原创界面说明图,帮助区分异常退出和手动停止,不是真实运行截图。

保存配置并重新应用项目

编辑器中保存 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 重新应用配置,通常就能解释大多数“容器为什么没按预期恢复”的问题。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>