Dockerfile 中 CMD 和 ENTRYPOINT 有什么区别?

ENTRYPOINT 定义容器的固定主程序,CMD 提供默认参数(可被 docker run 覆盖);二者常搭配使用:ENTRYPOINT 定命令、CMD 定默认参数。本文用实例讲透。

最佳实践
Dockerfile 中 CMD 和 ENTRYPOINT 有什么区别?封面

一句话区别:ENTRYPOINT 指定容器启动时执行的主程序**(不易被覆盖),CMD 指定默认命令或默认参数——docker run 时追加的参数会整个替换掉 CMD,但只会作为参数追加到 ENTRYPOINT 后面。两者组合的标准模式:ENTRYPOINT 定可执行文件,CMD 定它的默认参数。**

先理解默认机制

FROM ubuntu
CMD sleep 10

容器启动时实际执行的是 /bin/sh -c "sleep 10"——因为基础镜像默认 ENTRYPOINT 是 shell,CMD 只是传进去的参数。docker run myimg sleep 20整体覆盖 CMD,变成 sleep 20

ENTRYPOINT 的行为

FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]
  • docker run myimg → 执行 sleep 10(ENTRYPOINT + CMD 默认参数)
  • docker run myimg 30 → 执行 sleep 30(CMD 被替换,ENTRYPOINT 不变)

对比表

场景 CMD ENTRYPOINT
docker run img 新命令 的效果 新命令替换 CMD 新命令作为 ENTRYPOINT 的参数
用途 提供默认值 固定容器用途
覆盖方式 命令行直接覆盖 --entrypoint 显式覆盖
推荐形式 exec 数组形式 exec 数组形式

实用模式

模式一:可执行文件 + 默认参数(上文 sleep 例子),适合工具型镜像。

模式二:包装脚本

ENTRYPOINT ["/entrypoint.sh"]   # 脚本里做初始化,最后 exec "$@"
CMD ["nginx", "-g", "daemon off;"]

官方 nginx/mysql 镜像都是这个套路:entrypoint 脚本处理环境变量、初始化数据目录,最后 exec "$@" 把 CMD 跑起来。

只用 CMD:适合"容器即应用"的简单场景,用户 run 时传什么就执行什么。

常见问题(FAQ)

Q:两者都用 shell 形式(不带方括号)有什么问题?
A:shell 形式会以 /bin/sh -c 包裹,主进程 PID 不是 1,接收不到 docker stop 的 SIGTERM,优雅停机失效。生产镜像一律用 exec 数组形式。

Q:想进容器调试而不启动主程序?
A:docker run -it --entrypoint /bin/sh myimg,显式覆盖 ENTRYPOINT。

Q:K8s 里对应哪个字段?
A:command 覆盖 ENTRYPOINT,args 覆盖 CMD。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台