ENTRYPOINT 是容器主程序,CMD 是其默认参数;二者共存时,运行时参数覆盖 CMD 并追加至 ENTRYPOINT;推荐 exec 形式以确保 PID 1 和信号正常传递。

ENTRYPOINT 和 CMD 都是定义容器启动行为的指令,但角色完全不同:ENTRYPOINT 是“主程序”,CMD 是“默认参数”。理解这个分工,就能避免镜像启动失败或参数被意外丢弃的问题。
职责定位不同
ENTRYPOINT 指定容器必须运行的可执行文件,比如 /app/server 或 nginx。它让镜像表现得像一个独立命令,不可跳过(除非用 --entrypoint 强制覆盖)。
CMD 则只提供参数,默认值,比如 --port 8080 或 start。当没有 ENTRYPOINT 时,CMD 才会作为主命令执行;一旦设了 ENTRYPOINT,CMD 就自动降级为它的默认参数。
运行时参数如何传递
使用 docker run myimage arg1 arg2 时:
- 仅含 CMD:整个 CMD 被完全替换,原命令丢失
- 仅含 ENTRYPOINT:
arg1 arg2会追加到 ENTRYPOINT 后面,组成完整命令 - 两者共存:ENTRYPOINT 固定,CMD 作为初始参数;运行时传入的参数会覆盖 CMD,但继续传给 ENTRYPOINT
例如:
ENTRYPOINT ["curl"]<br>CMD ["-I", "https://example.com"]
执行
docker run myimage https://google.com → 实际运行 curl https://google.com。
语法与信号处理建议
两者都支持 shell 形式(如 CMD echo hello)和 exec 形式(如 CMD ["echo", "hello"]),但强烈推荐后者:
- exec 形式让进程直接成为 PID 1,能正常接收
SIGTERM等信号,支持优雅退出 - shell 形式会多一层
/bin/sh -c包装,导致信号无法透传,容器可能无法被docker stop正常终止 - exec 形式中环境变量不会自动展开(如
$HOME),需在脚本内处理或改用ENV+SHELL配合
典型误用与修正方式
常见错误是把主程序写进 CMD:
- ❌ 错误写法:
CMD ["nginx", "-g", "daemon off;"]→ 运行docker run img bash时,Nginx 根本不启动 - ✅ 正确写法:
ENTRYPOINT ["nginx", "-g", "daemon off;"]<br>CMD []
→ 主进程锁定,调试时可灵活加参数,如docker run img -t - ✅ 更实用组合:
ENTRYPOINT ["/entrypoint.sh"]<br>CMD ["--config", "/etc/app.yaml"]
→ 用 shell 脚本封装初始化逻辑,CMD 提供可调配置

















