7.4 CMD 容器启动命令
何时使用 CMD,何时使用 ENTRYPOINT?
在深入 CMD 的细节之前,我们需要理解一个关键问题:CMD 和 ENTRYPOINT 应该在什么时候使用?
这是 Dockerfile 使用中最常见的困惑之一。简单的答案是:
CMD:定义容器的“默认命令”。如果用户在
docker run时提供命令,CMD 会被覆盖ENTRYPOINT:定义容器的“入口脚本”。通常用于启动应用的某个特定部分
决策树:
你的容器是否有不可变的启动逻辑? 比如需要先做一些初始化工作,然后才运行应用 → 使用 ENTRYPOINT
用户经常会在
docker run时传入不同的命令吗? → 使用 CMD(让用户灵活覆盖)大多数情况下,你希望容器始终以相同的方式启动? → 使用 ENTRYPOINT
更多细节见 7.5 ENTRYPOINT 指令。
7.4.1 什么是 CMD
CMD 指令用于指定容器启动时默认执行的命令。它定义了容器的 “主进程”。
核心概念:容器的生命周期 = 主进程的生命周期。CMD 指定的命令就是这个主进程。
7.4.2 语法格式
CMD 有三种格式:
exec 格式
CMD ["可执行文件", "参数1", "参数2"]
✅推荐
shell 格式
CMD 命令 参数1 参数2
⚠️ 简单场景
参数格式
CMD ["参数1", "参数2"]
配合 ENTRYPOINT
exec 格式:推荐
优点:
直接执行指定程序,是容器的 PID 1
正确接收信号(如 SIGTERM)
无需 shell 解析
shell 格式
实际执行:会被包装为 sh -c
优点:可以使用 $HOME 这类 shell 变量展开、管道等 shell 特性
缺点:主进程是 sh,信号无法正确传递给应用
7.4.3 exec 格式 vs shell 格式
主进程
指定的程序
/bin/sh
信号传递
✅ 正确
❌ 无法传递
$VAR shell 展开
❌ 不自动展开;环境变量仍会传入进程
✅ 自动展开
推荐使用
✅ 大多数场景
需要 shell 特性时
信号传递问题示例
7.4.4 运行时覆盖 CMD
docker run 后的命令会覆盖 Dockerfile 中的 CMD:
7.4.5 经典错误:容器立即退出
错误示例
原因分析
正确做法
7.4.6 CMD vs ENTRYPOINT
CMD
默认命令
docker run 参数会 覆盖 它
ENTRYPOINT
入口点
docker run 参数会 追加 到它后面
单独使用 CMD
搭配 ENTRYPOINT
详见 ENTRYPOINT 入口点章节。
7.4.7 最佳实践
1. 优先使用 exec 格式
2. 确保应用在前台运行
3. 使用双引号
4. 配合 ENTRYPOINT 使用
7.4.8 常见问题
Q:CMD 可以写多个吗?
不可以。多个 CMD 只有最后一个生效:
Q:如何在 CMD 中使用环境变量?
Q:为什么我的容器不响应 Ctrl+C?
可能是使用了 shell 格式,信号被 sh 吃掉了:
最后更新于