cmd shell格式以/bin/sh -c启动,shell为pid 1,无法正确传递sigterm;exec格式以json数组直接执行,应用为pid 1,支持信号响应与优雅关闭,生产环境应优先使用。
docker 容器启动命令中,shell 格式和exec 格式决定进程如何被初始化,直接影响信号传递、pid 1 行为和容器生命周期管理。写错会导致容器无法响应 docker stop、无法正确捕获 sigterm、甚至启动失败。
shell 格式:适用于简单命令,但有 PID 1 陷阱
语法:["command", "arg1", "arg2"] 是 exec 格式;而 command arg1 arg2(无引号、无方括号)是 shell 格式 —— 实际等价于 /bin/sh -c "command arg1 arg2"。
- 容器内真正的 PID 1 是
/bin/sh,不是你的应用进程,导致SIGTERM不会直接发给应用 - 应用无法作为前台进程接收终止信号,
docker stop可能超时后强制 kill - 适合调试或临时运行单条命令,例如:
docker run alpine echo "hello" - 不推荐用于生产服务镜像的
CMD或ENTRYPOINT
exec 格式:推荐标准写法,保障信号与进程模型正确
语法:必须是 JSON 数组形式,每个参数独立成字符串,如 ["nginx", "-g", "daemon off;"] 或 ["python", "app.py"]。
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
- 你的应用直接成为 PID 1,能正常接收
SIGTERM、SIGHUP等信号 - 支持优雅关闭:应用可注册信号处理器,完成清理后退出
- Docker 停止容器时,先发
SIGTERM给该进程,等待默认 10 秒后才SIGKILL - 在 Dockerfile 中应始终用 exec 格式写
CMD和ENTRYPOINT,例如:CMD ["node", "server.js"]或ENTRYPOINT ["./entrypoint.sh"]
常见错误与修正示例
- ❌ 错误:
CMD python app.py(shell 格式)→ 启动/bin/sh -c "python app.py",sh 是 PID 1 - ✅ 正确:
CMD ["python", "app.py"](exec 格式)→ python 直接是 PID 1 - ❌ 错误:
ENTRYPOINT ["/bin/bash", "-c", "npm start"]→ 多了一层 shell 封装 - ✅ 正确:
ENTRYPOINT ["npm", "start"](前提是 npm 可执行文件在 PATH 中且容器已配置好环境) - ⚠️ 注意:如果必须用 shell 功能(如管道、变量展开),应显式调用
sh -c并确保主进程可被信号控制,例如:ENTRYPOINT ["sh", "-c", "exec node server.js"](exec替换当前 shell 进程)
验证格式是否生效的小技巧
运行容器后,进入查看进程树:
docker exec -it <container> ps aux</container>- 若看到
/bin/sh -c xxx在 PID 1 位置 → shell 格式 - 若看到你的应用(如
nginx、python)在 PID 1 → exec 格式成功 - 再试
docker stop <container></container>,观察日志是否显示应用主动关闭(而非被 kill)










