compose.override.yaml 是怎么和 compose.yaml 合并的?哪些字段是覆盖,哪些是追加?想把 base 里的 ports 删掉怎么写?这篇不启动容器,直接看 docker compose config 展开后的结果。
只有 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 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。
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 是否支持这两个标签,没有测。