bigywater.tech
Docker · 65

Compose 覆盖文件:多个 -f 的合并规则

compose.override.yaml 是怎么和 compose.yaml 合并的?哪些字段是覆盖,哪些是追加?想把 base 里的 ports 删掉怎么写?这篇不启动容器,直接看 docker compose config 展开后的结果。

9901 和 9902
ports 列表是追加:base 和 override 的端口都在
alpine:3.18 vs 3.19
-f 的顺序不同,最终 image 不同(最后一个文件优先)
ports=[]
override 里写 ports: !reset [] 后合并结果的端口

自动合并

实测 · 本机执行输出
  只有 compose.yaml(-f 显式指定,不自动加 override):image=alpine:3.20  command=['sleep', '100']  environment={'KEEP': 'from-base', 'MODE': 'base'}  ports=[('9901', 80)]  volumes=[('/srv/a', '/data/a'), ('/srv/b', '/data/b')]  labels={'owner': 'team-a', 'tier': 'base'}  depends_on=['db']
  不带 -f(自动读取 compose.yaml + compose.override.yaml):image=alpine:3.19  command=['sleep', '200']  environment={'EXTRA': 'only-in-override', 'KEEP': 'from-base', 'MODE': 'override'}  ports=[('9901', 80), ('9902', 80)]  volumes=[('/srv/a', '/data/a'), ('/srv/c', '/data/b')]  labels={'owner': 'team-a', 'tier': 'override'}  depends_on=['db']

不带 -f 时,docker compose 读取 compose.yaml 并自动叠加 compose.override.yaml;一旦用 -f 显式指定,就不会再自动加 override。

合并规则

实测 · 本机执行输出
  image / command 这类单值:override 覆盖 base(image 从 alpine:3.20 变成 alpine:3.19,command 从 sleep 100 变成 sleep 200)
  environment(映射):按键合并,MODE 被覆盖、KEEP 保留、EXTRA 新增
  ports(列表):[('9901', 80), ('9902', 80)](两个都在,是追加)
  volumes(列表):[('/srv/a', '/data/a'), ('/srv/c', '/data/b')](target 相同的 /data/b 被换成 override 的源,/data/a 保留)
  labels(映射):按键合并:{'owner': 'team-a', 'tier': 'override'}

单值(image、command)被覆盖;映射(environment、labels)按键合并;ports 列表追加,所以想「只在开发时多开一个端口」可以写在 override 里;volumes 以挂载目标为键,同一个目标会被替换。

多个 -f

实测 · 本机执行输出
  -f compose.yaml -f compose.override.yaml -f extra.yaml → image = alpine:3.18
  -f compose.yaml -f extra.yaml -f compose.override.yaml → image = alpine:3.19

后面的覆盖前面的:同样三个文件,顺序不同,最终 image 一个是 alpine:3.18,一个是 alpine:3.19。

!reset 与 !override

实测 · 本机执行输出
  image=alpine:3.20  command=['sleep', '100']  environment={'KEEP': 'from-base', 'MODE': 'base'}  ports=[]  volumes=[('/srv/z', '/data/z')]  labels={}  depends_on=[]

要删掉 base 里的列表,用 !reset [];要整体替换而不是合并,用 !override。我只在这个版本(v5.5.1)里验证,旧版 compose 是否支持这两个标签,没有测。

分步演示

compose 多文件合并
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。Docker Compose v5.5.1;只用 docker compose config --format json 展开配置,没有启动容器;ports 的发布端口只是配置值,没有实际占用;实验后已删除临时文件
    • 没有验证:extends 与 include 的合并规则、配置合并后实际启动的容器、env_file 的合并、docker compose config 对环境变量插值的结果、旧版本 compose 的行为
    京ICP备2026067502号-1京公网安备11010502063487号