ENTRYPOINT 有两种模式:Exec 模式(推荐)以 JSON 数组形式直接执行程序,PID 1 即主进程,信号可透传,CMD 参数追加;Shell 模式以字符串形式经 /bin/sh -c 执行,PID 1 为 shell,信号不自动转发,CMD 通常失效。

ENTRYPOINT 指令用于配置容器启动时执行的命令,它和 CMD 协同工作,但语义更“固定”。Docker 中 ENTRYPOINT 有两种写法:**Exec 模式(推荐)** 和 **Shell 模式**,它们在进程管理、信号传递、环境变量展开、参数继承等方面有本质区别。
Exec 模式:直接执行程序,信号可透传
写法为 JSON 数组形式:ENTRYPOINT ["executable", "param1", "param2"]。Docker 将其作为 exec 系统调用直接运行,不经过 shell 解释器。
- 容器 PID 1 就是该 executable,能正确接收
SIGTERM等信号(例如docker stop可正常终止主进程) - 不会自动展开环境变量(如
$HOME),需显式用sh -c包裹或在程序内处理 - CMD 提供的参数会作为附加参数追加到 ENTRYPOINT 后面(不是覆盖),适合构建可复用镜像
- 典型用法:
ENTRYPOINT ["nginx", "-g", "daemon off;"],CMD ["--prefix", "/app"]→ 最终执行nginx -g "daemon off;" --prefix /app
Shell 模式:通过 /bin/sh -c 执行,信号被拦截
写法为字符串形式:ENTRYPOINT command param1 param2。Docker 会将其包装为 /bin/sh -c "command param1 param2" 运行。
- PID 1 是
/bin/sh,实际程序是子进程;docker stop发送的信号默认只到 shell,无法自动转发给子进程(除非手动 trap 处理) - 支持环境变量展开(如
ENTRYPOINT echo $HOME),也支持管道、重定向等 shell 特性 - CMD 的内容会被忽略(除非在 shell 字符串中显式引用
$@),灵活性低且不易组合 - 常见于简单调试场景,例如:
ENTRYPOINT echo "Starting..." && exec myapp(注意要加exec替换 shell 进程)
关键差异总结
选择哪种模式,核心看是否需要可靠信号处理和参数组合能力:
- 生产服务类镜像(如 Nginx、Redis、自研后台服务)——必须用 Exec 模式,确保优雅退出
- 需要环境变量或 shell 语法(如条件判断、文件检测)——可在 Exec 模式中调用
sh -c,例如:ENTRYPOINT ["sh", "-c", "echo $VERSION && exec myapp"],并用exec确保 PID 1 替换 - Shell 模式下若想让 CMD 生效,得手动写成:
ENTRYPOINT /bin/sh -c 'myapp "$@"' --,其中--后的内容会被 CMD 替换,但这已接近绕过设计本意
一个易错点:CMD 和 ENTRYPOINT 的组合逻辑
只有 Exec 模式下 CMD 才真正“有意义”:
- 两者都是 Exec 模式:
ENTRYPOINT ["node"]+CMD ["app.js"]→ 启动node app.js - ENTRYPOINT 是 Shell 模式:
ENTRYPOINT node app.js→ CMD 完全失效(除非你在字符串里写$@并配合--) - 混合模式(不推荐):ENTRYPOINT Shell + CMD Exec,行为不可预测,应避免

















