docker compose unpause 使用指南:恢复暂停的 Compose 服务容器
【免费下载链接】composeDefine and run multi-container applications with Docker项目地址: https://gitcode.com/GitHub_Trending/compose/compose
docker compose unpause是 Docker Compose 用于恢复(Unpause)被暂停(Paused)的服务容器的生命周期管理命令,通常与docker compose pause成对使用。本文以 docs/reference/compose_unpause.md 命令参考为骨架,结合本仓库中 CLI 注册、后端实现与端到端测试源码,讲解命令语法、--dry-run参数行为、底层执行流程及实际使用中的边界场景。读完本文,你将能准确理解 unpause 的适用范围,并能在多服务项目中正确恢复单个或多个服务的运行状态。
命令速览:与 pause 对应的恢复操作
按该命令的官方说明,其作用一句话即可概括:
Unpauses paused containers of a service(恢复某个服务中被暂停的容器)。
pause / unpause 在 Docker Compose 的项目生命周期管理(docs/reference/compose_pause.md)中是紧密配对的一对操作:
docker compose pause暂停(冻结)运行中的服务容器,使其进程被挂起;docker compose unpause恢复被暂停的容器,使其在原状态原位置继续运行,且不会重新创建容器。
两者的实现代码位于同一文件中:暂停走s.pause,恢复走s.unPause,结构完全对称,可见 pkg/compose/pause.go。
需要特别区分的是:unpause 不是 restart,也不是 start。docker compose restart会先停止再重新启动容器(进程重启),docker compose unpause则只是解除冻结,进程保持原 PID 与运行现场。关于容器各状态间的转换关系,可对照docker compose ps的状态输出(cmd/compose/ps.go)进行观察。
语法与基本用法
从 cmd/compose/pause.go 中unpauseCommand的定义可以确定命令用法为:
docker compose unpause [SERVICE...]Short描述为 "Unpause services"。其中:
- 不带任何
SERVICE参数:恢复当前 Compose 项目中所有被暂停的服务容器; - 指定一个或多个
SERVICE名称:只恢复这些服务对应的被暂停容器; ValidArgsFunction: completeServiceNames(...)意味着该命令支持服务名自动补全。
常用示例
恢复项目中所有被暂停的容器:
docker compose unpause只恢复某个服务(例如db)中处于 paused 状态的容器,其他服务的暂停状态不受影响:
docker compose unpause db一次恢复多个指定服务:
docker compose unpause web db与暂停操作配合的典型生命周期示例:
# 1) 后台启动项目 docker compose up -d # 2) 暂停 web 服务(db 等服务仍保持运行) docker compose pause web # 3) 需要时恢复 web 服务,容器不会被重新创建 docker compose unpause webOptions 参数说明
命令参考文档中给出的 Options 表如下:
| Name | Type | Default | Description |
|---|---|---|---|
--dry-run | bool | Execute command in dry run mode |
--dry-run是布尔开关,无默认值(即默认关闭,false)。该参数并非 unpause 独有,而是 Compose 根命令提供的持久化(persistent)标志:从 cmd/compose/compose.go 可以看到它被注册在根命令上:
c.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "Execute command in dry run mode")当用户传入--dry-run时,根命令的PersistentPreRunE会检测该标志并向后端注入干跑选项(cmd/compose/compose.go):
// dry run detection if dryRun { backendOptions.Add(compose.WithDryRun) }启用后命令走 dry-run 路径(对应项目中的 pkg/dryrun/dryrunclient.go),即展示将要执行的操作但不真正改动容器状态,适合在脚本化环境或 CI 中先验证命令行为:
docker compose --dry-run unpause db底层执行流程与源码解析
CLI 层:参数收集与后端分发
在 cmd/compose/pause.go 中,runUnPause完成两项工作:
- 通过
opts.projectOrName(ctx, dockerCli, services...)解析出当前项目与项目名; - 通过
withBackend(...)将调用分发到 Compose 后端,传入api.PauseOptions{Services: services, Project: project}。
可见pause与unpause在 API 层共用同一套api.PauseOptions(包含待操作的 Services 列表与 Project 模型),命令对象在 cmd/compose/compose.go 中被注册为根命令的子命令。
Backend 层:定位容器并逐个解除暂停
核心实现在 pkg/compose/pause.go:
func (s *composeService) UnPause(ctx context.Context, projectName string, options api.PauseOptions) error { return Run(ctx, func(ctx context.Context) error { return s.unPause(ctx, strings.ToLower(projectName), options) }, "unpause", s.events) } func (s *composeService) unPause(ctx context.Context, projectName string, options api.PauseOptions) error { containers, err := s.getContainers(ctx, projectName, oneOffExclude, false, options.Services...) if err != nil { return err } if options.Project != nil { containers = containers.filter(isService(options.Project.ServiceNames()...)) } return forEachContainerConcurrent(ctx, containers, func(ctx context.Context, ctr container.Summary) error { _, err := s.apiClient().ContainerUnpause(ctx, ctr.ID, client.ContainerUnpauseOptions{}) if err == nil { s.events.On(newEvent(getContainerProgressName(ctr), api.Done, "Unpaused")) } return err }) }执行流程可分为四个阶段:
- 项目名归一化:对传入的
projectName做strings.ToLower,避免因大小写差异定位不到容器; - 容器定位:
getContainers(ctx, projectName, oneOffExclude, false, options.Services...)会按项目名查询容器,oneOffExclude表示排除一次性(one-off,如docker compose run创建的)容器,只处理服务容器;若指定了services,则只筛选对应服务的容器; - 服务白名单过滤:当携带
options.Project模型时,再用isService(project.ServiceNames()...)过滤,确保只处理当前 Compose 模型中声明的服务容器; - 并发恢复 + 事件上报:
forEachContainerConcurrent并发地对每个容器调用 Docker Engine APIContainerUnpause;成功后通过事件系统上报"Unpaused"状态事件(见newEvent(getContainerProgressName(ctr), api.Done, "Unpaused")),进度可在docker compose unpause的 TTY 输出中看到;任一容器失败则返回对应错误。
值得注意的实现细节:unpause 以单个容器为粒度执行,这与 pause 的实现(pkg/compose/pause.go,调用ContainerPause)完全对称——服务名在此只是“选择哪些容器”的过滤条件,真正被恢复的是容器的 paused 状态本身。
端到端验证:从测试用例看真实行为
本仓库在 pkg/e2e/pause_test.go 中提供了针对 pause/unpause 的端到端场景测试,用TestPause描述了完整行为链:
1. up 启动 a、b 两个服务 -> 两者状态均为 running 2. docker compose pause a -> a 变为 paused,b 仍为 running 3. docker compose unpause a -> a 恢复为 running,b 不受影响测试还断言了NotRecreated("a", "b"),证明 unpause 只是恢复容器运行状态,不会重建任何容器。对应测试使用的示例项目文件见 pkg/e2e/testdata/TestPause/compose.yaml,是最小的双服务演示环境:
services: a: image: alpine init: true command: sleep infinity b: image: alpine init: true command: sleep infinity需要关注的边界行为
同一测试文件还覆盖了若干边界场景,体现了 unpause/pause 与 Docker Engine 行为的一致性:
- 对未在运行的服务执行操作是空操作:
TestPauseServiceNotRunning表明对“没有任何容器”的服务执行 pause 会被接受(// TODO: docker pause errors in this case, should Compose be consistent?注释亦记录了与docker pause的差异); - 对已暂停服务再次 pause 会失败:
TestPauseServiceAlreadyPaused断言第二次pause退出码为 1,并输出包含already paused的错误信息; - 对模型不存在的服务会被拒绝:
TestPauseServiceDoesNotExist断言对未知服务执行 pause 会报no such service: does_not_exist并返回退出码 1。
虽然以上用例以 pause 为主体,但同一套容器定位与状态机逻辑同样作用于 unpause:实践中对一个本就处于 running 状态的容器执行 unpause,其表现取决于 Docker Engine 对“非 paused 容器调用 unpause”的语义,通常不会有破坏性副作用;而“服务不在模型中”这类错误则会在定位容器阶段就被拦截。
适用场景与注意事项总结
- 配合 pause 做资源让渡:当某服务短期内无需处理流量(如批处理间隙)时,可先用
docker compose pause冻结它释放 CPU,需要时用docker compose unpause原地恢复,避免 stop/start 带来的重启开销; - 精确到服务而非整项目:利用
docker compose unpause <service>的过滤语义,实现细粒度的选择性恢复; - 确认状态再操作:可通过 cmd/compose/ps.go 查看容器状态(paused/running)后再决定对哪些服务执行 unpause;
- dry-run 先行验证:在自动化脚本中可加
--dry-run先确认将被影响的服务集合; - unpause 不等于 restart:unpause 不会重建或重启容器(有
NotRecreated测试断言背书),如需更换配置或镜像请使用docker compose up/restart。
如需进一步了解命令参考中的其他生命周期操作(如暂停命令docker compose pause、停止docker compose stop、重启docker compose restart),可查阅 docs/reference/ 目录下的对应命令文档,并结合各自实现源码深入学习。
【免费下载链接】composeDefine and run multi-container applications with Docker项目地址: https://gitcode.com/GitHub_Trending/compose/compose
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考