Docker Compose `docker compose up` 命令完全指南:构建、创建、启动与重建的编排核心
2026/9/9 20:42:12 网站建设 项目流程

Docker Composedocker compose up命令完全指南:构建、创建、启动与重建的编排核心

【免费下载链接】composeDefine and run multi-container applications with Docker项目地址: https://gitcode.com/GitHub_Trending/compose/compose

本文基于本仓库(Docker Compose)的官方命令参考文档 docs/reference/compose_up.md 编写,并结合cmd/pkg/下的命令实现与测试用例展开源码级解析。

docker compose up是 Docker Compose 中使用频率最高的单一入口命令:它负责构建镜像、拉取镜像、创建并启动服务容器,并在前台模式下汇总聚合各容器的日志输出。本指南将系统讲解该命令的完整行为模型、全部选项参数、重建/级联/等待策略以及pre_start生命周期钩子的故障排查流程,帮助你掌握"一条命令拉起整个应用栈"背后可精确控制的分阶段语义。

docker compose up 的职责与完整生命周期

官方文档对docker compose up的定义是:为服务构建、创建、启动并附着到容器(Builds, (re)creates, starts, and attaches to containers for a service)。如果相关联的服务尚未运行,它也会顺带启动这些关联服务(dependency),因此它天然具备"从零拉起整个应用"的能力。

从源码调用链看,命令的核心实现在 cmd/compose/up.go,其底层最终落到 pkg/compose/up.go 的composeService.Up

func (s *composeService) Up(ctx context.Context, project *types.Project, options api.UpOptions) error { err := Run(ctx, ..., func(ctx context.Context) error { err := s.create(ctx, project, options.Create) // 阶段一:创建容器 if err != nil { return err } if options.Start.Attach == nil { // 阶段二:后台模式直接启动 return s.start(ctx, project.Name, options.Start, nil) } return nil }, "up", s.events) ... return s.runInteractiveUp(ctx, project, options) // 前台模式:附着日志 + 交互 }

由此可以总结出docker compose up内部依次经历的阶段:

  1. 构建 / 拉取:若配置需要且策略允许,先执行镜像 build 或 pull;
  2. 创建(Create):创建各服务容器(此时并不启动,等价于docker compose create);
  3. 启动(Start):启动已创建的容器及其依赖服务;
  4. 附着(Attach,前台模式):聚合各容器输出,行为类似docker compose logs --follow;当命令退出时,所有容器被停止。

命令格式为:

docker compose up [OPTIONS] [SERVICE...]

不指定SERVICE时作用于 compose 文件中的全部服务;指定一个或多个服务名时,默认仍会连带其依赖服务(除非传入--no-deps)。实现上通过upOptions.apply完成服务子集筛选(cmd/compose/up.go),若结合--no-deps则使用types.IgnoreDependencies忽略依赖。

全量选项速查表

下表完整收录自 docs/reference/compose_up.md,与 cmd/compose/up.go 中实际注册的 cobra flags 一一对应:

名称类型默认值说明
--abort-on-container-exitbool任一容器停止时停止所有容器,与-d不兼容
--abort-on-container-failurebool任一容器以失败退出时停止所有容器,与-d不兼容
--always-recreate-depsbool重建依赖容器,与--no-recreate不兼容
--attachstringArray仅附着到指定服务,与--attach-dependencies不兼容
--attach-dependenciesbool同时附着到依赖服务的日志输出
--buildbool启动容器前先构建镜像
-d,--detachbool分离模式:后台运行容器
--dry-runbool以演练(dry run)模式执行命令
--exit-code-fromstring返回指定服务容器的退出码,隐含--abort-on-container-exit
--force-recreatebool即使配置与镜像未变化也重建容器
--menubool前台附着时启用交互快捷键,与--detach不兼容;也可由环境变量COMPOSE_MENU控制
--no-attachstringArray不附着(不流式输出日志)到指定服务
--no-buildbool即使策略允许也不构建镜像
--no-colorbool单色输出
--no-depsbool不启动关联服务
--no-log-prefixbool日志中不打印前缀
--no-recreatebool容器已存在则不重建,与--force-recreate不兼容
--no-startbool只创建不启动服务
--pullstringpolicy运行前拉取镜像("always"\|"missing"\|"never"
--quiet-buildbool抑制构建输出
--quiet-pullbool拉取时不打印进度信息
--remove-orphansbool移除不在 compose 文件中定义的服务容器
-V,--renew-anon-volumesbool重建匿名卷,而非从旧容器继承数据
--scalestringArray将 SERVICE 扩缩到 NUM 个实例,覆盖 compose 文件中的scale设置
-t,--timeoutint0附着或容器已运行时用于关停容器的超时秒数
--timestampsbool显示时间戳
--waitbool等待服务处于 running/healthy,隐含分离模式
--wait-timeoutint0等待项目达到 running/healthy 的最大秒数
-w,--watchbool监听源码,文件更新时重建/刷新容器
-y,--yesbool对所有提示默认回答 yes,非交互式运行

标志间冲突校验:不可组合的选项

这些"不兼容"并非口头约定,而是在PreRunE阶段由 cmd/compose/up.go 的validateFlags强校验的。部分典型约束包括:

  • --detach不能与--abort-on-container-exit--abort-on-container-failure--attach--attach-dependencies--watch组合;
  • --wait自动隐含分离模式up.Detach = true),因此同样不能再与上述附着类选项组合;
  • --force-recreate--no-recreate--always-recreate-deps--no-recreate--no-recreate--renew-anon-volumes--build--no-build--no-build--watch两两互斥;
  • --exit-code-from--abort-on-container-failure可叠加;--abort-on-container-exit--abort-on-container-failure不可同时使用;
  • --wait-timeout必须是非负整数。

前台 vs 后台:attach / detach 的输出控制模型

官方文档明确了三种常见运行形态:

$ docker compose up # 前台:聚合日志,Ctrl+C 退出后停止全部容器 $ docker compose up --detach # 后台:容器持续运行,命令立即返回 $ docker compose up --no-start # 只创建不启动(等价 create 阶段)

前台的"附着输出"默认包含所有被启动的服务(含依赖),因此默认输出形态等同于docker compose logs --follow。当某些服务日志过于冗长时,可用三组标志精细裁剪:

  • --attach <service>:只附着指定服务(可重复),此时无法再附着依赖,故与--attach-dependencies互斥;
  • --attach-dependencies:连依赖服务的日志一起附着;
  • --no-attach <service>:从附着集合中剔除指定服务,保留其余服务的输出。

实现细节(cmd/compose/up.go):--attach给出的服务名必须是被启动项目的一部分,否则直接报错cannot attach to services not included in up--no-attach则作为过滤器在运行时从集合中RemoveAll。另外,compose YAML 中服务若声明attach: false,该服务默认就不会被自动附着(除非显式--attach)。--no-log-prefix关闭每行日志的<service> |前缀,--timestamps追加时间戳,--no-color关闭 ANSI 彩色输出,这三者共同决定日志渲染外观(对应 pkg/compose 的日志消费者构建处)。

重建策略:diverged / force / never 三种模式的取舍

docker compose up已有旧容器时,默认会根据"服务的配置或镜像自容器创建以来是否发生变化"来决定是否重建。变化的容器会被停止并重建,且保留已挂载的卷(mounted volumes);未变化的容器则保持原样。

从源码看,三种策略被建模为常量(pkg/api/api.go):

  • RecreateDiverged = "diverged":默认策略——仅当容器配置与 compose 模型出现分歧(diverges)时才重建;
  • RecreateForce = "force":无条件重建;
  • RecreateNever = "never":绝不重建。

CLI 层将用户标志翻译为这些策略(cmd/compose/create.go):

func (opts createOptions) recreateStrategy() string { if opts.noRecreate { return api.RecreateNever } if opts.forceRecreate { return api.RecreateForce } if opts.noInherit { // -V / --renew-anon-volumes return api.RecreateForce } return api.RecreateDiverged } func (opts createOptions) dependenciesRecreateStrategy() string { if opts.noRecreate { return api.RecreateNever } if opts.recreateDeps { return api.RecreateForce // --always-recreate-deps } return api.RecreateDiverged }

日常典型用法:

$ docker compose up # 只在配置/镜像变化时重建 $ docker compose up --no-recreate # 已存在容器一律不重建(例如只是想补启动缺失的服务) $ docker compose up --force-recreate # 强制重建全部容器(如想应用运行时的环境变更) $ docker compose up --always-recreate-deps # 每次重建依赖容器(常用于 CI 确保依赖最新)

注意--renew-anon-volumes-V)会强制重建并从策略上丢弃旧匿名卷数据,因其与"保留数据"的继承语义冲突,故与--no-recreate互斥。--timeout-t)则作用于关停容器时的宽限期(秒),仅当用户在命令行显式指定时才会覆盖默认值(GetTimeout 依据timeChanged判断)。

Build 与 Pull 的精细控制

docker compose up的拉取默认策略是policy,即由镜像的pull_policy决定是否/何时拉取(注册默认值"pull""policy")。若显式传入--pull,则只接受三个取值之一:alwaysmissingnever,且会把所选策略应用到项目全部服务(cmd/compose/create.go 中Apply遍历服务覆写PullPolicy)。无效取值会报invalid --pull option

镜像构建相关的标志分三档:

  • --build:强制在启动前构建所有带build上下文的服务(实现上等效于把这些服务的pull_policy置为build,见 Apply);
  • --no-build:关闭构建——即使某个服务按策略需要本地构建(如pull_policy: build)也跳过;该标志与--watch互斥;
  • --quiet-build/--quiet-pull:分别抑制构建进度与拉取进度条输出。

实际构建以api.BuildOptions形式合并进api.CreateOptions,且会覆盖"显式指定的服务 + 其依赖"这一完整集合(cmd/compose/up.go),保证了依赖镜像缺位时 up 仍能自举构建。

退出码、信号处理与级联停止

官方文档对退出语义给出明确的契约:

  • 命令执行过程中遇到错误,退出码为1
  • 前台运行中被SIGINT(Ctrl+C)或SIGTERM中断时,所有容器被停止,退出码为0

升级版的级联(cascade)行为由三个标志提供,其中--exit-code-from <service>特别适合"启动完就跑"的任务型编排——它返回所选服务容器的退出码,并隐含启用--abort-on-container-exit,即任何容器退出都会停止整栈:

func (opts upOptions) OnExit() api.Cascade { switch { case opts.cascadeStop: return api.CascadeStop // --abort-on-container-exit case opts.cascadeFail: return api.CascadeFail // --abort-on-container-failure default: return api.CascadeIgnore } }

(见 cmd/compose/up.go;--exit-code-from会把cascadeStop置真,见 validateFlags。)

典型场景示例——构建测试矩阵后按被测服务退出码判定 CI 成败:

$ docker compose up --exit-code-from tests --abort-on-container-failure $ echo $? # 拿到 tests 服务容器的真实退出码

同时,级联停止与"前台附着输出"天然绑定,因此它们全部与-d/--wait互斥。

等待就绪:--wait / --wait-timeout

--waitdocker compose up在容器启动后继续等待,直到项目内服务达到running/healthy状态(结合服务healthcheck与依赖条件判定),隐含分离模式,适合自动化脚本在 up 之后立即消费服务。等待时长上限由--wait-timeout(秒)控制,超过则报错;两个参数在源码中分别落到api.StartOptions.WaitWaitTimeout(cmd/compose/up.go)。仓库中的端到端样例 pkg/e2e/testdata/TestUpWait/compose.yaml 展示了配合depends_on: condition: service_completed_successfully使用一次性任务的典型形态。

源码热更新:-w / --watch

-w, --watchup转为开发模式:附着输出的同时监听项目源码目录,文件变更即触发对应服务的镜像重建或容器刷新(refresh)。实现上由 pkg/compose/up.go 中创建的Watcher驱动,并可与交互菜单联动(见下文)。注意 watch 的语义要求可构建,因此与--no-build互斥;更多细节可参考仓库中的 compose_watch.md 与pkg/watch/目录下的 watcher 实现。

扩缩容与孤儿容器清理

  • --scale SERVICE=NUM:命令行级扩缩容,覆盖 compose 文件中的scale/deploy.replicas;格式错误(缺少=或非数字)会由applyScaleOpts直接报错(cmd/compose/create.go);
  • --remove-orphans:清理"属于当前项目但未在 compose 文件中定义"的孤儿容器。

值得一提的是这些行为同样受到环境变量的影响(定义见 cmd/compose/compose.go):

  • COMPOSE_REMOVE_ORPHANS:当命令行未显式指定--remove-orphans时,取其布尔值作为默认行为(up.go 的 PreRunE);
  • COMPOSE_IGNORE_ORPHANS:从项目环境读取,若与--remove-orphans同时为真会直接报错冲突(up.go)。

交互式导航菜单:--menu 与 COMPOSE_MENU

前台附着模式下可启用交互式快捷键菜单(--menu)。其默认开启逻辑较为讲究(resolveNavigationMenu,cmd/compose/up.go):

  1. 输出非 TTY(例如被管道化)时强制关闭;
  2. 未显式传--menu时读取环境变量COMPOSE_MENU(取值true/false);
  3. 两者都未提供时默认true

最终菜单是否真正生效还要求当前 display 模式非 plain 且 stdin 为终端(见 cmd/compose/up.go 的组合条件)。由于它服务于前台附着,与--detach不兼容。启用后可通过快捷键在附着日志中执行暂停、终止、切换时间戳等操作(菜单与 watcher、detach 能力的接线在 pkg/compose/up.go)。

pre_start 生命周期钩子:失败时的保留与排查

Compose 支持通过 compose 文件中的pre_start钩子在服务容器真正启动前运行一次性任务容器。官方文档明确了失败语义:当某个pre_start钩子以非零码退出时,Compose 会中止该服务的启动,并保留(retain)这个钩子容器以便排查。参考 e2e 样例 pkg/e2e/testdata/TestPreStartHookSuccess/compose.yaml:

services: sample: image: alpine command: sh -c 'cat /shared/init.txt && sleep 5' volumes: - data:/shared pre_start: - image: alpine command: sh -c 'echo "initialized" > /shared/init.txt' volumes: data:

失败后的三条排查命令

钩子容器带有com.docker.compose.hook=pre_start标签,因此可精确过滤定位:

$ docker ps -a --filter label=com.docker.compose.hook=pre_start $ docker logs <container-id>

钩子容器的自动清理机制

源码中的钩子实现位于 pkg/compose/pre_start.go:

  • 每次runPreStart开始时(pre_start.go),会先校验钩子配置(当前不支持per_replica: true,会直接报错并不触发任何 I/O),随后按声明的顺序顺序执行各钩子,任一失败即中断并向外抛错门控服务启动;
  • 每个钩子以临时容器形式运行,通过VolumesFrom共享服务容器的卷、接入同一网络;数据写入请使用命名卷或 bind mount(匿名卷与 tmpfs 按副本隔离,不会共享给钩子);
  • 执行前会自动removeOrphanPreStartContainers:把上一次失败遗留的同项目同服务HookLabel=pre_start钩子容器清理掉,避免累积。因此下一次docker compose up前会自动清掉旧钩子残留
  • docker compose down同样负责清理——pkg/compose/down.go 的removePreStartHookContainers会按项目名 + 服务名 + 钩子标签强制删除保留容器,对应测试TestDownRemovesRetainedPreStartHookContainers(pkg/compose/down_test.go)。

总结:一次docker compose up的决策路径

把以上要素串起来,一次不带参数的前台docker compose up大致走完这样一条决策链:

  1. 解析 compose 文件与选择的服务集合(校验--exit-code-from服务存在性、--no-deps依赖裁剪、空集合时报no service selected,见 up.go);
  2. --pull/--build/--no-build决定拉取与构建动作;
  3. 进入 create 阶段:依据--no-recreate/--force-recreate/--always-recreate-deps/--renew-anon-volumes决定每类容器的重建策略;
  4. 进入 start 阶段(除非--no-start),前台则构造日志消费者并按--attach/--no-attach/--attach-dependencies/attach: false决定附着集合;
  5. 若任一服务的pre_start钩子失败,中止启动并保留钩子容器供排查;
  6. 依据--abort-on-container-exit/--abort-on-container-failure/--exit-code-from设定级联退出语义,配合--wait/--wait-timeout决定命令何时返回及以何退出码返回。

理解这条路径后,无论是日常本地开发(up --watch)、后台常驻(up -d)、CI 就绪等待(up --wait --wait-timeout 60)还是任务退出码透传(up --exit-code-from job),都能准确选对参数组合并预判行为。

【免费下载链接】composeDefine and run multi-container applications with Docker项目地址: https://gitcode.com/GitHub_Trending/compose/compose

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询