DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Docker Compose 报 start_interval is not allowed

healthcheck 的 start_interval 需要 Compose 2.20.2 起的解析支持,启动阶段调度还要求 Engine 25.0 及以上。核对实际版本、兼容替代配置和重建后的健康检查状态。

给服务的 healthcheck 加上 start_interval: 5s 后,Compose 在读取配置时就停止了:

services.app.healthcheck Additional property start_interval is not allowed

这类报错发生在配置校验阶段,容器里的健康检查命令还没有运行。start_interval 从 Docker Compose 2.20.2 开始支持;实际执行配置的 Compose 过旧时,会把它当成不允许的属性。

引擎也有版本要求:启动阶段使用独立健康检查间隔,需要 Docker Engine 25.0 或更高版本。Compose 能解析 YAML,不等于连接到的引擎已经能按这个参数调度检查。本文针对 docker compose 管理的容器,不把 Swarm 的 stack 文件解析规则混在一起。

同时核对 Compose 和 Server 版本

在报错的同一台机器、同一账户和同一执行环境中运行:

docker compose version
docker version
docker context show
docker compose -f compose.yaml config

将 compose.yaml 换成实际文件名。原命令有多个 -f 或指定 --env-file 时,校验时也要保留相同参数;否则检查的可能不是报错时的配置。config 会展开配置中的变量,输出可能包含凭据,保存或分享前要脱敏。

第一条确认 Compose 插件版本。第二条要看 Server 部分,不能只看本机 Client:Docker context 可能指向远程引擎,升级本机客户端不会自动升级远端服务。CI 任务、容器内命令和交互终端也可能调用不同的 Compose。

如果原脚本调用的是 docker-compose,再用 docker-compose version 核对那个独立命令。命令带不带连字符本身不能代表版本新旧,应该确认真正执行的程序。

Compose 低于 2.20.2 时,按当前安装方式升级插件;Docker Desktop 环境通过其正常更新流程更新相关组件。引擎低于 25.0 时,还需要规划引擎升级,或采用下面的兼容配置。升级涉及宿主机服务时应安排维护窗口,并保留配置及数据备份。

不要靠修改文件顶部的 version: "3.8" 来获得这个能力。当前 Compose 使用实现所支持的 Compose Specification,顶部 version 只是兼容信息,不会替换程序或为旧解析器添加字段。

start_period 不是“等待结束才检查”

这几个参数分别控制不同的事情:

  • start_period 给初始化留出宽限期,在这段启动阶段内的探测失败通常不计入连续失败次数。
  • start_interval 控制启动阶段的检查间隔。
  • interval 控制常规检查间隔。

启动宽限期内仍然会探测。一旦检查成功,容器会被视为已启动,后续连续失败开始计数,检查也不应被理解为一定按短间隔持续跑满整个 start_period。

下面仅展示 app 服务需要合并的健康检查片段。保留原服务的镜像、启动命令、端口和卷;/usr/local/bin/healthcheck 是占位的检查程序路径,必须换成镜像里确实存在、能反映应用就绪状态的命令:

services:
  app:
    healthcheck:
      test: ["CMD", "/usr/local/bin/healthcheck"]
      start_period: 30s
      start_interval: 5s
      interval: 60s
      timeout: 3s
      retries: 3

检查命令应在成功时退出 0、失败时退出 1。不要使用总是返回成功的命令来绕过校验或等待问题。健康状态会影响等待 service_healthy 的依赖服务,错误的成功结果可能让依赖提前启动。

这些示例值不能保证应用在 30 秒内就绪。也不要拿日志之间的墙钟差值要求严格每 5 秒出现一条:探测执行耗时和调度会影响实际记录时间。

暂时不能升级时,明确接受检查频率的变化

如果当前 Compose 已支持其余健康检查字段,只是不接受 start_interval,可以先备份配置,删除这一项,并用普通 interval 表达兼容的检查频率。例如希望尽早发现启动成功,可以暂时采用:

services:
  app:
    healthcheck:
      test: ["CMD", "/usr/local/bin/healthcheck"]
      start_period: 30s
      interval: 5s
      timeout: 3s
      retries: 3

代价是应用启动成功后也会继续按这个较短间隔检查。若检查会访问数据库、外部接口或执行较重的命令,应评估持续负载;也可以保留原来的 interval: 60s,接受启动成功可能被较晚发现。

删除 start_interval 只解决该字段的兼容性,不等价于保留了“启动时快、稳定后慢”的行为。删除整个 healthcheck 或关闭检查,则会改变依赖等待条件,不应作为同等替代方案。

重建服务后核对实际配置和状态

配置检查通过后,在允许短暂中断、相关持久化数据已有备份的前提下,更新指定服务:

docker compose -f compose.yaml up -d app
docker compose -f compose.yaml ps app
docker compose -f compose.yaml ps -q app

将文件名和 app 换成实际值,并保持原项目参数一致。up 会按配置变化重建需要更新的容器;仅修改磁盘上的 YAML 并不能改变已经创建的容器配置。

从最后一条命令取到容器 ID 后,替换下面的 CONTAINER_ID:

docker inspect --format '{{json .Config.Healthcheck}}' CONTAINER_ID
docker inspect --format '{{json .State.Health}}' CONTAINER_ID

先看实际健康检查配置是否包含预期的参数,再看状态、探测退出码和日志时间。若配置中参数正确但探测一直失败,就转向检查程序、地址、权限和应用启动过程;此时问题已经不再是 YAML 不允许该字段。

回退时恢复备份的健康检查配置,再用相同项目参数执行 up -d app,并重新检查健康状态。不要为了回退健康检查参数删除数据库卷;宿主机引擎升级的回退应按原安装方式和版本兼容要求单独处理。