Docker Compose 报 service_completed_successfully 是无效条件
depends_on 拒绝 service_completed_successfully 时,核对实际调用的 Compose 版本和路径,区分旧独立程序与插件,保留迁移成功完成的启动条件。
在应用服务的 depends_on 中设置 condition: service_completed_successfully,本想等初始化或迁移任务成功结束再启动应用,Compose 却在解析文件时就报错:
condition contains "service_completed_successfully", which is an invalid type,
it should be a service_started, or a service_healthy
如果报错明确列出只接受后两种条件,先核对实际执行的 Compose 程序。旧版 Python docker-compose 1.28.4 会拒绝这个值;历史版本 1.29.0 才加入等待服务成功完成的条件。当前 Compose 支持该条件,因此“插件已经安装”与“部署脚本正在调用插件”需要分别确认。
这里处理配置校验阶段的无效条件错误。若文件能通过校验,只是初始化一直不退出,或应用提前启动,应继续查运行状态和最终依赖配置,不能直接套用旧版解析器的结论。以下命令面向 Linux 或其他使用 POSIX shell 的部署环境。
同时核对两个命令的版本
在发生错误的用户、终端或 CI 步骤中执行:
docker compose version
docker-compose version
command -v docker
command -v docker-compose
有些环境同时保留两个入口:docker compose 使用插件,docker-compose 仍指向旧 Python 程序。检查输出中的实际版本及路径;若一个命令不存在,保留这条结果即可,不需要为了凑齐命令再安装旧版。
不要仅凭连字符判断版本。有的环境会提供兼容入口或包装脚本,应以实际输出和调用路径为准。也不要用 Docker Engine 的版本代替 Compose 版本,两者不是同一个组件。
如果手动执行的是插件,部署日志却来自旧版程序,查看 Makefile、CI 配置、定时任务和发布脚本中的启动命令。自动化可能使用绝对路径,也可能在另一个用户的搜索路径中找到旧程序。在那个执行环境重新核对版本;只更新本机终端不会改变远程部署节点。
修改调用入口,保留原来的项目参数
如果插件已经可用且支持现有项目,可以将部署脚本中的旧入口改成 docker compose,保留原来的工作目录、项目名、全部配置文件和环境文件参数。例如原本使用多个文件,就不要在切换命令时顺便减少文件:
docker compose -p example-project \
-f compose.yaml -f compose.production.yaml \
config --quiet
example-project 和两个文件名都是示例,需替换为实际值。先执行配置校验,不要直接启动服务来判断解析器是否升级成功。
若插件尚未安装,按当前操作系统与既有 Docker 安装渠道安装受维护的 Compose 插件。对于已经配置 Docker 官方软件仓库、已经安装 Engine 和 CLI 的 Ubuntu 或 Debian,可以使用:
sudo apt-get update
sudo apt-get install docker-compose-plugin
docker compose version
未配置相应仓库的机器不能把这几行当作完整安装流程;其他发行版也不应直接照搬。手工安装的插件不会自动更新,要按原安装方式管理。
1.29.0 只是这个旧版功能的历史边界,不是建议现在安装它。切换前保存当前脚本、配置和版本记录,先在本机隔离环境检查项目兼容性。不要为了清理旧入口立即删除不明路径中的文件,先确认还有哪些自动化依赖它。
不必把完成条件改成启动条件
下面只展示字段关系。镜像与容器内命令是占位值,真实项目应保留自己的环境变量、网络、卷和其他设置:
services:
migrate:
image: example/app:approved-tag
command: ["/app/bin/migrate"]
restart: "no"
app:
image: example/app:approved-tag
command: ["/app/bin/serve"]
depends_on:
migrate:
condition: service_completed_successfully
migrate 应是执行完就退出的一次性任务,失败时必须返回非零退出码。app 的启动依赖它成功完成。不要把 migrate 写成永不退出的数据库进程,也不要在迁移失败后强行返回成功,否则等待条件无法表达真实结果。
把条件换成 service_started 虽然可能让旧解析器接受文件,却只要求依赖服务启动,不会等待迁移完成;这会改变应用启动的前提。常驻数据库的就绪判断通常应该通过健康检查和 service_healthy 表达,不能与一次性迁移任务混用。
当前 Compose 使用 Compose Specification,顶层 version 已经不再选择校验模式。把它从 "3.9" 改成 "2.4" 不能代替升级或切换实际解析器。本文也不把 Compose 的启动条件推广到 docker stack deploy 等其他部署入口。
校验通过后,再核对完成状态
去掉 --quiet 查看实际模型,确认 app 下仍保留指向 migrate 的完成条件:
docker compose -p example-project \
-f compose.yaml -f compose.production.yaml \
config
输出可能含环境变量中的敏感值,保存在受控位置,对外提供时先脱敏。若依赖在文件中存在,渲染结果却消失,这是另一种配置处理问题;仅升级命令入口不够,还要解决模型中丢失的依赖。
确认模型正确后,再按项目正常发布流程启动。初始化或迁移命令可能修改数据,先核对备份、重复执行条件和回退方式,不要反复重建任务容器来试验等待关系。对于同样使用上述项目参数的部署,可以这样查看状态和日志:
docker compose -p example-project \
-f compose.yaml -f compose.production.yaml \
ps --all
docker compose -p example-project \
-f compose.yaml -f compose.production.yaml \
logs --timestamps --tail 100 migrate app
ps --all 会包含已经退出的容器,适合检查一次性任务。核对迁移任务是否成功退出、日志是否显示预期迁移完成,以及应用是否能正常提供服务。任务仍在运行或非零退出时,应处理迁移自身的问题,不要通过降低依赖条件放行应用。
回退脚本和 Compose 配置不会撤销已经完成的数据迁移。若需要退回旧工具,而它不能理解完成条件,应停止继续发布并恢复经过验证的启动编排;不能删除条件后就把部署当作恢复成功。也不需要通过删除数据卷来修复这个解析错误。


