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

Docker CMD 收到字面量 ${STACK}:exec 形式不会展开容器环境变量

容器环境变量已经设置,CMD 参数却仍是 ${STACK}。核对入口与参数,使用应用环境配置或包装脚本,保留参数边界及原初始化步骤。

容器里已经设置 STACK=production,程序却收到 ${STACK},甚至提示该名称不存在。若启动参数写成 CMD ["--stack", "${STACK}"],变量未展开是这组参数的正常行为。JSON 数组不会自动调用 shell,Docker 也不会替应用解释其中的变量。

这类问题常发生在镜像有固定 ENTRYPOINT,部署平台只允许覆盖 CMD 参数时。本文面向 Linux 容器;是否能修改入口、镜像内是否有 shell,会决定可用办法。

变量已设置,不代表参数会被替换

以下为示例:

ENTRYPOINT ["/app/bin/worker"]
CMD ["--stack", "${STACK}"]

最终程序收到的参数是 --stack 和字面量 ${STACK}。环境变量与命令行参数是两份输入。只有程序自己读取环境变量,或确实由 shell 展开后构造参数,才会使用环境中的值。

先查看实际容器的入口和参数:

docker inspect --format '{{json .Config.Entrypoint}} {{json .Config.Cmd}}' CONTAINER_ID

CONTAINER_ID 替换成目标容器。若结果保留 ${STACK},检查入口脚本是否负责展开它;不能仅凭这段元数据断定程序最终收到什么。若入口没有这类逻辑,字面量会继续向下传递。不要为检查一个非敏感变量而把全部环境变量输出到共享日志。

若程序明确支持从 STACK 读取配置,优先直接配置这个变量,并删除冲突的命令行参数。是否支持以及参数、环境变量的优先级必须以应用本身为准。

能维护镜像时,用入口脚本构造参数

下面是自有镜像的示例入口,不适合直接替换第三方镜像的初始化入口。假设 /app/bin/worker 存在且可执行,它需要 --stack 参数:

#!/bin/sh
set -eu
: "${STACK:?STACK must be set and non-empty}"
exec /app/bin/worker --stack "$STACK" "$@"

将脚本保存为构建上下文中的 entrypoint.sh,Dockerfile 配置为:

COPY entrypoint.sh /usr/local/bin/app-entrypoint
RUN chmod 755 /usr/local/bin/app-entrypoint
ENTRYPOINT ["/usr/local/bin/app-entrypoint"]
CMD []

镜像必须提供 /bin/sh。脚本在变量缺失或为空时退出;双引号让一个值作为一个参数传入,不会被空格拆开;exec 用应用替换脚本进程。"$@" 保留额外参数边界,部署方不应再传重复的 --stack,以免应用按自己的重复参数规则覆盖它。

不要使用 eval 对传入字符串二次求值。需要的是读取一个变量,不是把变量内容当作新 shell 命令执行。

只能覆盖 CMD 时,先看入口允许什么

如果入口固定执行应用,改成 CMD ["sh", "-c", "..."] 往往只是把 sh、-c 传给该应用,随后出现未知参数错误。把 CMD 改成 shell 字符串也不能自动绕过固定入口。

这时可选的路径是使用应用支持的环境变量、由部署平台提前生成明确的参数值,或维护一个带包装入口的镜像。不要假设平台在 JSON 数组中支持容器环境插值。若使用平台自身的替换机制,要确认替换发生在部署端,值可能进入任务定义和审计记录,敏感信息不要这样传。

只有确认原入口可以安全替换、镜像包含 shell,并保留原初始化要求时,才考虑显式用 shell 启动应用。第三方入口可能还负责权限、配置生成和初始化,绕过它会引入另一类故障。

更新和成功标准

保存旧镜像和部署配置,在允许中断的窗口重新创建目标容器;仅重启旧容器不会替换镜像的 CMD 或入口。回退时恢复旧镜像及原启动参数,再按相同部署流程创建容器。

成功应同时满足:变量缺失时能给出可解释的错误,变量设置后应用使用实际值,原有附加参数仍被正确接收。检查应用日志或业务结果时不要输出秘密值。若参数已经正确而应用仍报错,再转向该值对应的资源、权限或配置检查。