docker-compose.dev.yml 生效——Compose 按 -f 的书写顺序从左到右层层合并,后面的文件覆盖/追加到前面的结果上。所以标准约定就是:基础文件在前,环境覆盖文件(dev / prod / local)在后。后者(docker-compose.dev.yml)优先级更高。 Compose 把 -f 后面的文件按顺序叠加到前面的结果上,最后一份文件的话语权最大。

1.同名service三种合并行为准则
| 字段类型 |
行为 |
典型字段 |
| 单值 |
后者整体替换前者 |
image、command、entrypoint、working_dir、container_name、restart、healthcheck.test |
| 映射(键值) |
逐键合并,同 key 后者赢,前者独有的保留 |
environment、labels、sysctls、extra_hosts、build.args |
| 列表 |
追加拼接,不会整体替换 |
ports、expose、volumes、devices、dns、secrets、configs、depends_on |
示例
1 2 3 4 5 6 7 8 9 10
| services: api: image: myapp:1.0 command: node server.js environment: LOG_LEVEL: info DB_HOST: db ports: - "8080:8080"
|
1 2 3 4 5 6 7 8 9 10
| services: api: image: myapp:dev command: nodemon server.js environment: LOG_LEVEL: debug DEBUG: "1" ports: - "9229:9229"
|
2.验证方式
1 2 3 4 5
| docker compose -f docker-compose.yml -f docker-compose.dev.yml config
docker compose -f docker-compose.yml -f docker-compose.dev.yml config --services
|
3.注意的坑
- 列表是追加,不是替换:想改掉基础文件里的端口/挂载,直接在 dev 里写新值是做不到的,结果会变成两个都存在;同宿主端口重复会直接报端口冲突。要么改基础文件,要么用
!reset 语法(Compose v2.24+ 支持 ports: !reset [])清空后再写。
- 相对路径基准:
build.context、env_file、volumes 的相对路径是相对项目目录(默认即第一个 -f 文件所在目录)解析,而不是各文件自己的目录。跨目录放 compose 文件时很容易踩坑,用 docker compose config 看解析结果最稳。
--build 与合并无关,只影响是否重新构建镜像。
- 用
COMPOSE_FILE=a.yml:b.yml 环境变量时逻辑相同,也是从左到右。