首页/云/Docker 容器速查/JSON 数组形式的写法细节
镜像与构建107 条

JSON 数组形式的写法细节

exec 形式必须用双引号 JSON 数组,单引号或拼接字符串都会解析失败;数组形式不做变量展开,参数原样传递。

Docker 容器速查云更新于 2026-10-13

JSON 数组形式是什么

RUN、CMD、ENTRYPOINT 都有两种写法:shell 形式把整行交给容器的 shell 解释,exec 形式用 JSON 数组直接指定可执行文件与参数。JSON 形式的规则很简单也很严格:必须是双引号的 JSON 数组,且数组内的参数原样传递,不做变量替换与通配符展开。理解这一点,就能解释为什么同样的变量写在数组里变成了字面量。

基本信息

正确写法CMD ["node", "server.js"]
错误写法CMD ['node', 'server.js'](单引号不是合法 JSON)
变量行为数组内 $HOME 之类不会被替换,原样作为参数传入
执行方式exec 形式不经过 shell,因此没有管道、重定向与通配符
需要展开时套一层 shell:["/bin/sh", "-c", "exec app --port ${PORT:-8080}"]
组合规则ENTRYPOINT 数组 + CMD 数组时,CMD 作为默认参数追加到 ENTRYPOINT 后

典型使用场景

  • 信号传递:exec 形式让应用进程成为 PID 1,docker stop 的 SIGTERM 能直达进程
  • 参数固定、不需要 shell 特性的启动命令
  • 需要变量展开或管道时显式套 sh -c,把 shell 行为写清楚而不是依赖隐式规则
  • 多阶段构建的 COPY --from 与 ENTRYPOINT 配合,产物路径完全可控
  • 排查启动报错时查看镜像配置里保存的原始数组内容

写法对照

写法对照
# exec 形式:推荐,PID 1 就是应用本身
CMD ["node", "server.js"]

# 字面量陷阱:这里输出的是 $HOME 这几个字符,不是家目录路径
CMD ["echo", "$HOME"]

# 确实需要变量展开与默认值,就显式套一层 shell
CMD ["/bin/sh", "-c", "exec node server.js --port ${PORT:-8080}"]

# shell 形式:整行交给 /bin/sh -c,能用管道,但 PID 1 变成 shell
CMD node server.js | tee /var/log/app.log

两种形式对比

维度exec(JSON 数组)shell(整行)
解析方式直接执行,不经 shell/bin/sh -c 解释整行
变量展开不展开按 shell 规则展开
管道与重定向不支持支持
信号接收方应用进程本身最外层 shell
适用建议启动应用首选需要 shell 能力时使用
校验方法:docker inspect 镜像后看 Config.Cmd 与 Config.Entrypoint 里保存的数组,即可确认是否被当成字符串处理;容器启动报可执行文件找不到时,先核对这里。
Windows 路径在 JSON 字符串里要写成双反斜杠或改用正斜杠,反斜杠转义错误是这类镜像启动失败的高频原因。

易错点

  • JSON 数组写坏时构建依然通过,容器启动才报可执行文件不存在或路径错误,排错要先看镜像里保存的原始配置
  • 把 shell 变量写进 exec 形式后取到字面量,应用读到端口为字符串 $PORT 之类的值并直接报错
  • exec 形式不支持重定向,想写日志文件必须套 shell 或在应用层实现,硬写 > 号会变成一段普通参数
  • 在 ENTRYPOINT 用 shell 形式启动,PID 1 变成 shell,停止时的 SIGTERM 送不到应用,容器只能等超时被强杀

数据来源与参考

  • Docker 官方文档:Dockerfile 格式(docs.docker.com)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌