cmd是可替换的默认命令,entrypoint是固定的执行入口;cmd定义默认动作但易被覆盖,entrypoint锁定主程序并接收追加参数,二者配合实现“固定程序+灵活参数”。

理解 CMD 和 ENTRYPOINT 的关键,不在于背定义,而在于看它们“谁会被覆盖、谁被当参数、谁真正变成 PID 1”。一句话:CMD 是可替换的默认命令,ENTRYPOINT 是固定的执行入口——它决定了容器“到底在运行什么程序”。
CMD 是默认行为,随时可以被换掉
CMD 设定的是容器启动时的默认动作,但这个动作非常“温柔”,一有外部干预就会让位。
- 如果 Dockerfile 中写了
CMD ["nginx", "-g", "daemon off;"],运行docker run myimg就会执行它 - 但只要加个命令,比如
docker run myimg bash,整个 CMD 就被丢弃,直接执行bash - Dockerfile 里写多个 CMD,只有最后一个生效;它不能和 ENTRYPOINT 搭配出“固定程序+灵活参数”的效果,除非你刻意用 CMD 仅提供参数
ENTRYPOINT 是程序本体,参数才可变
ENTRYPOINT 锁定了容器的主程序。你传进来的所有额外参数,不是去替换它,而是追加到它后面——这才是服务类镜像(如 Nginx、Redis、自定义 CLI 工具)的标准用法。
- 写成
ENTRYPOINT ["python", "app.py"],再运行docker run myapp --debug,实际执行的是python app.py --debug - 如果同时写了
ENTRYPOINT ["echo", "Hello"]和CMD ["World"],不带参数启动就是echo Hello World;带参数如docker run img !就变成echo Hello ! - 想彻底换掉 ENTRYPOINT?必须显式加
--entrypoint /bin/sh,否则它永远在最前面
格式选 exec 还是 shell?直接影响信号处理
两种写法表面相似,底层行为完全不同:
-
Exec 格式(推荐):
["nginx", "-g", "daemon off;"]—— nginx 直接成为 PID 1,能正常接收SIGTERM,docker stop可优雅退出 -
Shell 格式:
nginx -g "daemon off;"—— 实际启动的是/bin/sh -c 'nginx ...',PID 1 是 sh,nginx 是子进程,docker stop可能杀不掉 nginx,导致强制终止 - 注意:shell 格式的 ENTRYPOINT 会忽略 CMD 和
docker run后的参数,基本只用于调试,生产环境慎用
典型组合与使用场景
怎么搭配才合理?看你的镜像定位:
- 做通用基础镜像(如 Ubuntu、Alpine):只用 CMD,留给上层镜像或用户自由决定运行什么
-
封装一个具体服务(如官方 nginx 镜像):ENTRYPOINT 固定为
["/usr/sbin/nginx"],CMD 提供默认参数["-g", "daemon off;"] -
提供 CLI 工具镜像(如
curl、jq、自研命令行):ENTRYPOINT 设为工具本身,CMD 给常用选项,用户可轻松传参调用 -
需要调试入口:临时把 ENTRYPOINT 改成
["/bin/sh"],或者用docker run --entrypoint /bin/sh -it myimg进入交互










