Docker Compose 2.32.1 使用 extends 后丢失 depends_on
Compose 2.32.1 中,服务同时使用 extends 与 depends_on 时,显式依赖可能从最终配置中消失。说明如何核对渲染结果、确认修复版本,并在无法更新时展开继承,保留初始化等待条件。
服务同时写了 extends 和 depends_on,执行 docker compose config 却发现依赖整段消失:镜像等继承属性仍在,显式声明的启动条件已经不在最终配置中。依赖初始化任务的服务因此可能过早启动,而且配置校验不一定报错。
Docker Compose 2.32.1 存在这一配置处理缺陷。这里处理的是“文件里有依赖,渲染结果里没有”的情况;如果最终配置已经保留依赖,只是数据库还没就绪,应继续检查等待条件,不能直接归为同一个问题。
在最终配置中确认依赖是否还在
在实际部署环境查看 Compose 版本,再沿用部署时的文件和选项生成配置:
docker compose version
docker compose -f compose.yaml config
compose.yaml 替换为真实文件名。多文件项目要保留原来的全部 -f 参数及顺序;环境文件、项目名等选项也要一致。CI 和开发工具可能调用不同的 Compose 安装,应在发生问题的环境里检查,不能只看自己电脑上的版本。
config 输出的是解析、合并和变量处理后的实际模型,可能包含环境变量中的敏感值。检查时保存在受控位置,对外分享前先脱敏。
下面是用于说明字段关系的最小配置。镜像和容器内命令都是占位值,只用来理解配置,不应直接替换业务部署或拿来执行初始化任务:
services:
init:
image: example/app:approved-tag
command: ["/app/bin/initialize"]
app:
extends: init
command: ["/app/bin/serve"]
depends_on:
init:
condition: service_completed_successfully
app 自己声明了对 init 的依赖。期望的渲染结果应包含:
services:
app:
depends_on:
init:
condition: service_completed_successfully
required: true
这是应保留的局部字段,完整输出还会有镜像、命令和其他配置。required: true 是默认必需依赖;关键是目标服务和等待条件都还在。若 app 下整段 depends_on 消失,才符合本文的故障表现。
被误删的是当前服务自己声明的依赖
在这个历史缺陷中,配置加载器先合并被继承服务与当前服务,再从合并结果删除依赖相关字段。这会连当前服务显式写出的 depends_on 一起删掉。
修正后的处理将相关排除操作放到继承来源上,避免误删当前服务自己的依赖。因而,“不把来源服务的依赖照搬过来”和“删除当前服务明确声明的依赖”是两件不同的事,不能把后者当成合理的继承行为。
Compose 2.32.2 使用的配置库已经包含这项修复。已确认的故障版本是 2.32.1,不应把所有使用 extends 的版本都视为有问题;2.32.2 在这里是历史修复参照,也不是建议现在专门安装这个旧版本。
更新实际使用的 Compose,或暂时展开继承
优先按原安装渠道更新到经过项目兼容性验证的维护版本,然后重新生成配置,确认依赖恢复。这里要更新的是 Compose 插件;Docker Engine 的版本号不能代替 Compose 版本。手工安装的插件不会自动随包管理器更新,因此更新后仍要在原执行环境检查版本。
若暂时不能更新,可以在配置副本中移除受影响服务的 extends,把它实际需要的属性明确写出来,并保留自己的依赖关系。上面的最小例子可以展开为:
services:
init:
image: example/app:approved-tag
command: ["/app/bin/initialize"]
app:
image: example/app:approved-tag
command: ["/app/bin/serve"]
depends_on:
init:
condition: service_completed_successfully
这只是绕开该继承处理路径。真实服务还可能继承卷、环境变量、用户、工作目录、网络、健康检查等设置,不能只复制示例里的镜像。应与最近一次可用的完整配置比较;涉及外部文件时还要核对相对路径,避免把卷或环境文件指向别处。
不要仅增加固定等待时间来掩盖缺失依赖,也不要把条件改成更弱的 service_started。如果应用确实需要初始化任务成功结束,就要保留 service_completed_successfully,并确保任务在失败时返回非零退出码。长驻数据库服务则通常不会正常退出,不能为了套用这个例子给它设置“等待成功结束”的条件。
校验成功不等于启动条件正确
修改后再次查看完整 config 输出,确认依赖目标、条件和其他服务属性符合预期,然后运行只校验的形式:
docker compose -f compose.yaml config --quiet
这一步成功不能代替上一项内容检查:依赖被删掉后,剩下的模型本身也可能合法。对比渲染结果,确认启动约束是否真的恢复。
应用变更前保存 Compose 文件、插件版本记录和必要的数据备份,按项目正常发布流程处理。初始化或迁移任务可能写数据库,不要为验证等待关系反复运行它们;应先确认其重复执行条件及回退办法。需要更新容器时安排维护窗口,并保留容器可写层中尚未持久化的必要文件。
发布后结合初始化任务的退出状态、应用启动日志和实际业务请求确认顺序及结果。配置回退只恢复配置,不会撤销已经执行的数据迁移。若恢复到仍会丢失依赖的旧插件与原文件组合,应停止继续部署,不能把恢复文件当成服务已经恢复。


