
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.Upfunc (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内部依次经历的阶段构建 / 拉取若配置需要且策略允许先执行镜像 build 或 pull创建Create创建各服务容器此时并不启动等价于docker compose create启动Start启动已创建的容器及其依赖服务附着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 # 前台聚合日志CtrlC 退出后停止全部容器 $ 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.goRecreateDiverged diverged默认策略——仅当容器配置与 compose 模型出现分歧diverges时才重建RecreateForce force无条件重建RecreateNever never绝不重建。CLI 层将用户标志翻译为这些策略cmd/compose/create.gofunc (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则只接受三个取值之一always、missing、never且会把所选策略应用到项目全部服务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前台运行中被SIGINTCtrlC或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--wait让docker compose up在容器启动后继续等待直到项目内服务达到running/healthy状态结合服务healthcheck与依赖条件判定隐含分离模式适合自动化脚本在 up 之后立即消费服务。等待时长上限由--wait-timeout秒控制超过则报错两个参数在源码中分别落到api.StartOptions.Wait与WaitTimeoutcmd/compose/up.go。仓库中的端到端样例 pkg/e2e/testdata/TestUpWait/compose.yaml 展示了配合depends_on: condition: service_completed_successfully使用一次性任务的典型形态。源码热更新-w / --watch-w, --watch将up转为开发模式附着输出的同时监听项目源码目录文件变更即触发对应服务的镜像重建或容器刷新refresh。实现上由 pkg/compose/up.go 中创建的Watcher驱动并可与交互菜单联动见下文。注意 watch 的语义要求可构建因此与--no-build互斥更多细节可参考仓库中的 compose_watch.md 与pkg/watch/目录下的 watcher 实现。扩缩容与孤儿容器清理--scale SERVICENUM命令行级扩缩容覆盖 compose 文件中的scale/deploy.replicas格式错误缺少或非数字会由applyScaleOpts直接报错cmd/compose/create.go--remove-orphans清理属于当前项目但未在 compose 文件中定义的孤儿容器。值得一提的是这些行为同样受到环境变量的影响定义见 cmd/compose/compose.goCOMPOSE_REMOVE_ORPHANS当命令行未显式指定--remove-orphans时取其布尔值作为默认行为up.go 的 PreRunECOMPOSE_IGNORE_ORPHANS从项目环境读取若与--remove-orphans同时为真会直接报错冲突up.go。交互式导航菜单--menu 与 COMPOSE_MENU前台附着模式下可启用交互式快捷键菜单--menu。其默认开启逻辑较为讲究resolveNavigationMenucmd/compose/up.go输出非 TTY例如被管道化时强制关闭未显式传--menu时读取环境变量COMPOSE_MENU取值true/false两者都未提供时默认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.yamlservices: 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.hookpre_start标签因此可精确过滤定位$ docker ps -a --filter labelcom.docker.compose.hookpre_start $ docker logs container-id钩子容器的自动清理机制源码中的钩子实现位于 pkg/compose/pre_start.go每次runPreStart开始时pre_start.go会先校验钩子配置当前不支持per_replica: true会直接报错并不触发任何 I/O随后按声明的顺序顺序执行各钩子任一失败即中断并向外抛错门控服务启动每个钩子以临时容器形式运行通过VolumesFrom共享服务容器的卷、接入同一网络数据写入请使用命名卷或 bind mount匿名卷与 tmpfs 按副本隔离不会共享给钩子执行前会自动removeOrphanPreStartContainers把上一次失败遗留的同项目同服务HookLabelpre_start钩子容器清理掉避免累积。因此下一次docker compose up前会自动清掉旧钩子残留docker compose down同样负责清理——pkg/compose/down.go 的removePreStartHookContainers会按项目名 服务名 钩子标签强制删除保留容器对应测试TestDownRemovesRetainedPreStartHookContainerspkg/compose/down_test.go。总结一次docker compose up的决策路径把以上要素串起来一次不带参数的前台docker compose up大致走完这样一条决策链解析 compose 文件与选择的服务集合校验--exit-code-from服务存在性、--no-deps依赖裁剪、空集合时报no service selected见 up.go按--pull/--build/--no-build决定拉取与构建动作进入 create 阶段依据--no-recreate/--force-recreate/--always-recreate-deps/--renew-anon-volumes决定每类容器的重建策略进入 start 阶段除非--no-start前台则构造日志消费者并按--attach/--no-attach/--attach-dependencies/attach: false决定附着集合若任一服务的pre_start钩子失败中止启动并保留钩子容器供排查依据--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),仅供参考