Docker CMD 报带方括号的 not found:检查数组是否漏逗号
CMD漏逗号可能被当成shell字符串,导致错误里出现方括号命令名。检查JSON与实际启动字段,保留原入口约定后重建验证。
镜像里的程序明明存在,启动时却报类似 /bin/sh: 1: [worker,: not found。如果错误中的程序名多了开头的 [ 或逗号,先核对 Dockerfile 的 CMD 数组语法;一个漏掉的逗号可能使本来想写的 exec 形式被当成 shell 命令。
这里针对 Linux 镜像、CMD 内容存在但 JSON 语法不合法的情况。普通 worker: not found、解释器缺失、挂载遮住程序等也可能导致启动失败,不能只凭 not found 就决定重写 CMD。
看着像数组,仍需要合法 JSON
例如下面的配置少了 "--mode" 与 "batch" 之间的逗号:
CMD ["/app/bin/worker", "--mode" "batch"]
当前 BuildKit 0.25.1 的相关 Dockerfile 解析器会尝试 JSON 解析;这种语法错误会落入命令字符串处理,而不是得到期待的参数数组。随后默认 shell 可能把包含左方括号的内容当作命令名,出现带方括号的 not found。具体报错格式还取决于镜像的 shell 与启动入口。
并非所有错误数组都用同一方式处理。例如数组成员不是字符串时,相关解析器会报类型错误,不能把任何无效 JSON 都描述成必然静默转为 shell。
正确形式应为:
CMD ["/app/bin/worker", "--mode", "batch"]
每个字符串是一个参数,成员之间有逗号,JSON 字符串使用双引号。不要把单引号数组、中文弯引号或 shell 的续写方式当作合法 JSON。
同时检查镜像与容器的启动字段
先保留失败镜像的实际版本或摘要,再只读查看启动配置。以下名称均需替换:
docker image inspect app:failed --format '{{json .Config.Entrypoint}} {{json .Config.Cmd}}'
docker inspect app-container --format '{{json .Config.Entrypoint}} {{json .Config.Cmd}}'
对照 Dockerfile、镜像与实际容器。如果预期的参数列表变成 shell 加一整段带方括号的字符串,与这条处理路径相符。若镜像已经是合法数组,而容器配置不同,再查创建时的命令覆盖;不要继续改一个没有被部署使用的 Dockerfile。
入口脚本也可能重新解释参数,因此字段是诊断依据,仍需与完整错误和实际启动链对应。程序的完整路径存在,不能抵消开头 [ 导致命令名变化的问题;同样,路径不存在时,补逗号也不会创建程序。
修语法时保留原入口的约定
确认缺少逗号后,仅修正相应数组。镜像没有固定 ENTRYPOINT 时,CMD 需要包含可执行程序;镜像的 ENTRYPOINT 已经固定调用应用时,CMD 可以只提供该应用的默认参数。不能把示例中的程序路径机械地再加到每一个镜像中。
如果新入口覆盖了基础镜像、默认 CMD 反而变成空值,应另查ENTRYPOINT 对继承 CMD 的影响。那种问题不靠修一个已不存在的数组逗号解决。
也不必为了让错误消失把原命令全部改成 shell 字符串。合法 exec 数组可以直接保留参数边界;shell 形式会引入变量展开与信号路径等差异。若后续程序收到字面量变量名,可另看exec CMD 不展开环境变量,那不是本次数组漏逗号的原因。
重新构建后验证真实启动
用新标签构建修正镜像,先核对它的启动字段,再在隔离环境按原入口启动。成功应同时满足:目标程序被正确调用、每个参数按应用要求传入、原先的初始化和业务步骤正常。构建完成只说明镜像生成,CMD 本身并不在构建阶段执行。
正式替换容器时保存旧镜像与部署参数,并处理持久数据和在途请求。restart 旧容器不会让它采用新镜像的 CMD。需要回退时恢复原镜像及对应配置;不要通过删卷、扩大权限或重装同一个程序来处理已经确认的数组语法问题。


