CMD 指令指定容器启动时默认执行的命令,仅在 docker run 时生效,一个 Dockerfile 中仅最后一个 CMD 生效;支持 Shell、Exec 和 Exec+默认参数三种格式,分别适用于简单命令、前台服务及与 ENTRYPOINT 配合传参。

Dockerfile 中的 CMD 指令用于指定容器启动时默认执行的命令,是实现容器自动运行的核心方式之一。它不会在构建镜像时执行,而是在 docker run 启动容器时才生效,且一个 Dockerfile 中只能有一个 CMD 生效(后定义的会覆盖前一个)。
CMD 的三种写法及适用场景
Shell 格式(推荐用于简单命令):CMD echo "Hello from container"
Docker 会通过 /bin/sh -c 执行,适合单条、无需环境变量扩展或复杂逻辑的命令。
Exec 格式(推荐用于主进程,如 Web 服务):CMD ["nginx", "-g", "daemon off;"]
以 JSON 数组形式直接调用可执行文件,不经过 shell,PID 为 1,便于信号接收(如 Ctrl+C 正常终止),适合长期运行的前台服务。
Exec + 默认参数格式(配合 ENTRYPOINT 使用):
ENTRYPOINT ["python", "app.py"]<br> CMD ["--port", "8080"]
CMD 提供 ENTRYPOINT 命令的默认参数,运行容器时可被 docker run 后的参数覆盖,灵活性高。
确保 CMD 正确生效的关键点
- 避免在 CMD 中使用后台命令(如
service nginx start或加&),否则容器会立即退出——Docker 要求 PID 1 进程保持前台运行 - 若需多条启动命令(如初始化数据库再启动服务),应封装进 shell 脚本(如
entrypoint.sh),再由 CMD 调用:CMD ["./entrypoint.sh"] - CMD 不会继承构建阶段的 shell 环境变量,如需变量,改用
ENV显式声明,或在 exec 格式中用sh -c包裹(但会失去 PID 1 优势) - 当 Dockerfile 中同时存在 ENTRYPOINT 和 CMD,且都用 exec 格式时,CMD 内容作为 ENTRYPOINT 的参数传入,不是独立执行
常见错误与调试方法
容器启动即退出?快速排查:
- 运行容器时加
-it并指定/bin/sh覆盖 CMD:docker run -it --rm your-image /bin/sh,手动执行 CMD 命令看是否报错 - 检查日志:
docker logs,尤其注意权限、路径、依赖缺失等提示 - 确认 CMD 中的可执行文件已正确复制进镜像,并具有执行权限(如
RUN chmod +x ./start.sh) - 使用
docker inspect查看实际生效的 Cmd 字段,验证是否被覆盖或解析异常
替代方案:何时该用 ENTRYPOINT 而非 CMD
当镜像用途明确、必须以某个程序为入口(如 CLI 工具、固定服务),且希望用户仅能修改参数而非整个命令时,优先用 ENTRYPOINT + CMD 组合。例如:
ENTRYPOINT ["java", "-jar", "/app.jar"]<br> CMD ["--server.port=8080"]
这样用户运行 docker run myapp --server.port=9000 就能覆盖默认端口,而不会误写成 docker run myapp bash 导致 Java 不启动。










