Dockerfile 中 CMD 和 ENTRYPOINT 区别
所属分类 docker
浏览量 4
一. 核心区别
ENTRYPOINT:
容器启动时 必须执行的命令 / 程序,优先执行
不可被覆盖(用 --entrypoint 才能覆盖),适合定义容器主进程。
CMD:
默认参数 / 默认命令,可以被覆盖,
适合给 ENTRYPOINT 传参,或单独写默认启动命令。
二. 几种使用方式
1. 单独用 CMD(最简单)
CMD ["echo", "Hello Docker"]
运行:docker run 镜像 → 输出 Hello Docker
覆盖:docker run 镜像 echo Hi → 输出 Hi(CMD 被直接替换)
适合:简单容器、测试、临时命令。
2. 单独用 ENTRYPOINT(固定命令)
ENTRYPOINT ["echo", "Hello"]
运行:docker run 镜像 → Hello
运行:docker run 镜像 Docker → Hello Docker(后面内容变成参数)
想覆盖必须:docker run --entrypoint ls 镜像
适合:必须固定启动的主程序(Nginx、Java、Python 服务)
3. ENTRYPOINT + CMD(最标准、最推荐)
ENTRYPOINT ["echo"] # 固定主命令
CMD ["Hello Docker"] # 默认参数
直接运行:docker run 镜像 → echo Hello Docker
传参运行:docker run 镜像 Hi → echo Hi(CMD 被替换)
CMD 被 docker run 命令直接覆盖 !!!
生产环境标准写法:固定主程序 + 灵活传参。
三. exec 格式 vs shell 格式
1. exec 格式(推荐 )
ENTRYPOINT ["nginx", "-g", "daemon off;"]
CMD ["python", "app.py"]
不会启动额外 shell
信号能传递(docker stop 能正常停止容器)
必须双引号 + JSON 数组格式
ENTRYPOINT ["java","-jar","app.jar"]
CMD ["--env","prod"]
直接创建进程作为 PID 1
能接收 docker stop 信号,优雅停机
不经过 /bin/sh -c,无 shell ,环境变量自动解析
2. shell 格式(不推荐 )
ENTRYPOINT nginx -g "daemon off;"
CMD python app.py
会用 /bin/sh -c 执行
无法接收信号,容器可能无法优雅关闭
ENTRYPOINT java -jar app.jar
实际等价:/bin/sh -c "java -jar app.jar"
PID 1 是 sh,业务进程是子进程
docker stop 收不到信号,容易杀不掉容器、僵尸进程
生产禁止用 Shell 模式
四. 其他
强制覆盖 ENTRYPOINT?
docker run --entrypoint 或 docker-compose 里 entrypoint 字段。
临时覆盖入口程序
docker run --entrypoint /bin/sh 镜像名
混用 Shell 和 Exec 格式ENTRYPOINT 数组、CMD 写字符串,参数拼接错乱。
PID 1 不是业务进程Shell 模式导致,容器无法正常 stop,只能 kill -9。
一个 Dockerfile 只能最后一条 ENTRYPOINT / CMD 生效,前面的会被覆盖
优先级:
ENTRYPOINT + CMD > 单独 ENTRYPOINT > 单独 CMD
ENTRYPOINT ["java","-jar","app.jar"]
CMD ["--spring.profiles.active=dev"]
docker run 镜像 --spring.profiles.active=prod
自动替换 CMD 部分,变成:
java -jar app.jar --spring.profiles.active=prod
上一篇
docker compose up 和 restart 的区别
2026年了 docker还流行吗
docker inspect 查看 镜像/容器 信息