Docker Compose include 拆分多环境服务定义
来源:17golang原创
时间:2026-10-10 18:09:56 129浏览 收藏
Docker Compose 项目一旦同时维护开发、测试和生产环境,最先变乱的通常不是服务本身,而是一个文件里不断叠加的变量、端口和路径。更稳妥的拆法是让主 compose.yaml 只负责组合,把公共服务和每个环境的服务定义放到独立文件,再用 include 载入。
官方地址:https://docs.docker.com/reference/compose-file/include/
include 会把被引入文件作为独立的 Compose 应用模型解析,然后把资源带回当前模型;相对路径默认以被引入文件所在目录为基准。本文按“文件边界、变量、覆盖、预览”四个设置点拆开,最后用 docker compose config 检查合并结果。
先确认能力和文件边界
在编辑器中打开项目根目录,左侧资源管理器先建立下面的结构。这里的目录名只是教程示例,重点是让不同环境拥有自己的项目目录,避免把所有相对路径都解释成根目录路径。
# 先确认本机 Compose 版本,避免把旧版能力当成配置错误
docker compose version
# 目录职责:公共服务只放可复用资源,环境目录保存差异
infra/
common/compose.yaml
dev/compose.yaml
prod/compose.yaml
compose.yaml
compose.override.yaml
如果版本过旧,先按团队的 Docker Desktop 或 Compose CLI 升级流程处理。不要为了让编辑器消除提示而在 YAML 里添加无效的 version 字段;Compose 使用当前规范解析文件。

把公共服务和环境服务拆开
在主文件的设置入口中只保留 include 和需要跨环境保留的入口服务。下面的 YAML 是最小结构:公共文件提供数据库,开发文件提供热更新服务,生产文件提供正式镜像。
# compose.yaml:只负责组合,不把所有服务细节堆在根文件
include:
- path: ./infra/common/compose.yaml
- path: ./infra/dev/compose.yaml
services:
gateway:
image: example/gateway:stable
depends_on:
- db # 直接引用被 include 文件带入的服务
# infra/common/compose.yaml:公共数据库和网络边界
services:
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
# infra/dev/compose.yaml:开发环境自己的应用服务
services:
web:
build:
context: ../..
environment:
APP_ENV: development
在编辑器里保存三个 YAML 后,先看左侧文件树是否把公共文件和环境文件分开,再检查每个 build.context。被引入文件中的相对路径默认从它自己的目录解释,这正是拆分配置时最容易误判的地方。
用 env_file 管理不同环境变量
当开发和生产只差数据库地址、镜像标签或日志级别时,不要复制整份服务定义。可以把变量文件绑定到对应的 include 条目。长语法同时提供 project_directory,需要改变相对路径基准时才显式设置它。
# compose.yaml:环境切换只改变 include 条目,不复制整棵服务树
include:
- path: ./infra/common/compose.yaml
- path: ./infra/prod/compose.yaml
project_directory: ./infra/prod
env_file:
- ./infra/prod/prod.env
# infra/prod/compose.yaml:变量通过 ${...} 进入服务定义
services:
web:
image: example/web:${WEB_TAG}
environment:
APP_ENV: ${APP_ENV}
LOG_LEVEL: ${LOG_LEVEL}
在编辑器的环境配置面板中分别打开 dev.env 和 prod.env,只保存非敏感的默认值;敏感值交给团队的密钥管理方式。当前项目的环境变量优先级高于 include 条目里的默认值,因此本地明确设置的值可以覆盖引入模型的默认值。
处理资源冲突和覆盖关系
include 的资源冲突会被 Compose 报告,不应该依赖“后加载的文件悄悄覆盖前面的服务”。如果确实要改第三方或公共服务,使用 include 自己的专用覆盖文件,或者使用根目录的 compose.override.yaml 表达本地调整。
# compose.yaml:把第三方模型和本地 override 放在同一个 include 条目
include:
- path:
- ./infra/common/compose.yaml
- ./infra/common/override.yaml
# compose.override.yaml:本地开发临时打开调试端口
services:
web:
ports:
- "8080:8080" # 只改变本地入口,生产文件不需要这段映射
在编辑器中逐项确认:同名服务是否确实需要修改、覆盖文件是否只包含差异、生产环境是否会意外带上调试端口。若只是想组合文件,不要把 include 当作无限层级的覆盖机制;它更适合清楚地划分子域。
用 config 预览合并后的模型
最后在项目工具栏的“配置预览”入口执行下面的命令。它只解析 Compose 模型,不会启动容器,适合在提交前检查服务是否出现、变量是否展开、路径是否指向正确目录。
# 预览最终模型;--no-consistency 不要随意添加,先让冲突显式暴露
docker compose config
# 只查看服务名,快速确认 include 的服务已经进入当前模型
docker compose config --services
# 用生产文件单独预览,避免把开发 override 混进发布配置
docker compose -f compose.yaml config
检查右侧预览结果时,重点看 services、volumes、networks、镜像标签和宿主机路径。看到服务缺失时,先回到 include 的路径;看到变量为空时,先回到 env_file 与本地环境变量;看到资源冲突时,拆出专用 override,而不是继续增加同名定义。

一份可执行的回退清单
- 复制原来的单文件 Compose 配置到受保护的分支,先记录当前启动命令。
- 只迁移公共服务到
infra/common/compose.yaml,用docker compose config --services对照服务名。 - 一次只加入一个环境文件,检查相对路径和变量展开,再处理下一个环境。
- 出现资源冲突时保留冲突信息,新增明确的 override 文件,不直接删除原服务定义。
- 在变更评审中附上
config的关键片段;如果预览结果不符合预期,就切回原文件而不是先启动容器碰运气。
常见问题
include 和多次使用 -f 有什么区别?
-f 更像是从命令行选择并合并一组 Compose 文件;include 则把子 Compose 应用的目录和依赖关系写进模型,适合按团队或子域管理相对独立的配置。
为什么拆开后 volume 路径变了?
因为被引入 Compose 文件默认以自己的目录解析相对路径。先检查 project_directory,再决定是调整目录还是显式指定基准。
能不能用 include 覆盖同名服务?
不要依赖隐式覆盖。资源冲突应显式拆出专用 override 或根目录覆盖文件,先让 docker compose config 把问题暴露出来。
把 compose.yaml 收缩为组合入口、把服务按子域拆开,再用环境文件和 config 预览承接差异,通常比继续复制整份 YAML 更容易维护。真正提交前,优先核对相对路径、变量来源和冲突资源这三项。
-
160 收藏
-
105 收藏
-
420 收藏
-
276 收藏
-
175 收藏
-
459 收藏
-
449 收藏
-
477 收藏
-
文章 · 软件教程 | 6小时前 | 开发环境 · vs code · 软件教程 · devcontainer.json VS Code Dev Containers Dev Container Features 容器开发环境 开发工具复用378 收藏
-
360 收藏
-
254 收藏
-
文章 · 软件教程 | 20小时前 | CI/CD · gitHub actions · 软件教程 · GitHub Actions 环境保护规则 部署审批 Required reviewers production environment357 收藏
-
190 收藏
-
152 收藏
-
494 收藏
-
477 收藏
-
176 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习