What is the difference between CMD and ENTRYPOINT in a Dockerfile?
What is the difference between CMD and ENTRYPOINT in a Dockerfile?
技术背景
在使用 Docker 构建和运行容器时,CMD
和 ENTRYPOINT
是 Dockerfile
中两个重要的指令,它们都与容器启动时执行的命令有关。最初,Docker 有默认的入口点 /bin/sh -c
,但没有默认命令。随着需求的发展,为了实现更灵活的定制,引入了 ENTRYPOINT
和 --entrypoint
。
实现步骤
CMD
指令
CMD
用于为容器设置默认命令和/或参数,用户可以在运行容器时轻松覆盖这些默认值。如果 Dockerfile
中有多个 CMD
指令,只有最后一个会生效。
示例:
1 |
|
运行容器:
1 |
|
ENTRYPOINT
指令
ENTRYPOINT
用于定义容器启动时始终执行的命令,通常用于将容器作为可执行文件使用。除非使用 --entrypoint
标志,否则在启动容器时不能覆盖 ENTRYPOINT
。
示例:
1 |
|
运行容器:
1 |
|
CMD
和 ENTRYPOINT
结合使用
在很多情况下,结合使用 CMD
和 ENTRYPOINT
是最佳解决方案。ENTRYPOINT
定义可执行文件,CMD
则指定默认参数。
示例:
1 |
|
运行容器:
1 |
|
核心代码
以下是几个不同使用场景的 Dockerfile
示例:
仅使用 CMD
1 |
|
仅使用 ENTRYPOINT
1 |
|
ENTRYPOINT
和 CMD
结合使用
1 |
|
最佳实践
- 当需要默认命令且用户可轻松覆盖时:使用
CMD
。例如,创建一个包含各种工具的通用镜像,用户可以根据需要执行不同的命令。 - 当将容器作为可执行文件使用时:使用
ENTRYPOINT
。例如,创建一个专门用于执行ping
命令的镜像。 - 结合使用
CMD
和ENTRYPOINT
:让ENTRYPOINT
定义主要命令,CMD
提供默认参数。这样可以在保持主要功能的同时,允许用户灵活调整参数。
常见问题
1. 不指定 ENTRYPOINT
和 CMD
会怎样?
如果不指定 ENTRYPOINT
和 CMD
,Docker 将使用 /bin/sh -c
作为默认入口点,并在运行容器时使用用户传递的命令行参数(如果定义了 CMD
,则使用 CMD
的值)。
2. 如何覆盖 ENTRYPOINT
和 CMD
?
- 覆盖
CMD
:在运行容器时提供额外的参数,例如docker run my-image foo bar
会将CMD
覆盖为["foo", "bar"]
。 - 覆盖
ENTRYPOINT
:使用--entrypoint
标志,例如docker run my-image --entrypoint foo
会将ENTRYPOINT
覆盖为foo
。
3. CMD
和 ENTRYPOINT
采用不同格式(shell 形式和 exec/JSON 形式)有什么区别?
- shell 形式:
ENTRYPOINT "mycommand arg1"
会被转换为ENTRYPOINT ["/bin/sh", "-c", "\"mycommand arg1\""]
。 - exec/JSON 形式:
ENTRYPOINT ["mycommand", "arg1"]
保持不变。建议使用 exec/JSON 形式,以避免信号处理和其他边缘情况的问题。
What is the difference between CMD and ENTRYPOINT in a Dockerfile?
https://119291.xyz/posts/2025-05-12.difference-between-cmd-and-entrypoint-in-dockerfile/