在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
当前回答
这个公认的答案在解释历史方面非常棒。我发现这张表很好地解释了“CMD和ENTRYPOINT如何交互”的官方文档:
其他回答
CMD和ENTRYPOINT之间的直觉差异:
ENTRYPOINT:容器启动时运行的命令。CMD:容器启动时运行的命令,或ENTRYPOINT的参数(如果指定)。
是的,这令人困惑。
在运行docker run时,可以覆盖其中任何一个。
CMD和ENTRYPOINT之间的差异示例如下:
docker run -it --rm yourcontainer /bin/bash <-- /bin/bash overrides CMD
<-- /bin/bash does not override ENTRYPOINT
docker run -it --rm --entrypoint ls yourcontainer <-- overrides ENTRYPOINT with ls
docker run -it --rm --entrypoint ls yourcontainer -la <-- overrides ENTRYPOINT with ls and overrides CMD with -la
有关CMD和ENTRYPOINT之间差异的更多信息:
docker run的参数(例如/bin/bash)会覆盖我们在Dockerfile中编写的任何CMD命令。
ENTRYPOINT不能在运行时被docker run[args]等正常命令覆盖。docker运行结束时的args[args]作为ENTRYPOINT的参数提供。通过这种方式,我们可以创建一个像ls这样的普通二进制文件的容器。
因此,CMD可以作为ENTRYPOINT的默认参数,然后我们可以从[args]重写CMD参数。
ENTRYPOINT可以用--ENTRYPOINT重写。
根据docker文档,
CMD和ENTRYPOINT指令都定义执行什么命令当运行容器时。很少有规则描述合作。Dockerfile应至少指定CMD或ENTRYPOINT命令之一。将容器用作可执行文件时,应定义ENTRYPOINT。CMD应用作为ENTRYPOINT命令或在容器当使用可选参数运行容器时,CMD将被重写。
下表显示了对不同ENTRYPOINT/CMD组合执行的命令:
--无入口点
╔════════════════════════════╦═════════════════════════════╗
║ No CMD ║ error, not allowed ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD ["exec_cmd", "p1_cmd"] ║ exec_cmd p1_cmd ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD ["p1_cmd", "p2_cmd"] ║ p1_cmd p2_cmd ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD exec_cmd p1_cmd ║ /bin/sh -c exec_cmd p1_cmd ║
╚════════════════════════════╩═════════════════════════════╝
--入口点执行_入口p1_入口
╔════════════════════════════╦══════════════════════════════════╗
║ No CMD ║ /bin/sh -c exec_entry p1_entry ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD ["exec_cmd", "p1_cmd"] ║ /bin/sh -c exec_entry p1_entry ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD ["p1_cmd", "p2_cmd"] ║ /bin/sh -c exec_entry p1_entry ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD exec_cmd p1_cmd ║ /bin/sh -c exec_entry p1_entry ║
╚════════════════════════════╩══════════════════════════════════╝
--入口[“exec_entry”,“p1_entry“]
╔════════════════════════════╦═════════════════════════════════════════════════╗
║ No CMD ║ exec_entry p1_entry ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD ["exec_cmd", "p1_cmd"] ║ exec_entry p1_entry exec_cmd p1_cmd ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD ["p1_cmd", "p2_cmd"] ║ exec_entry p1_entry p1_cmd p2_cmd ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD exec_cmd p1_cmd ║ exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd ║
╚════════════════════════════╩═════════════════════════════════════════════════╝
大多数人在这里都解释得很好,所以我不会重复所有的答案。但为了得到一个好的感觉,我建议自己通过查看容器中的流程来测试它。
创建一个小型Dockerfile,格式如下:
FROM ubuntu:latest
CMD /bin/bash
构建它,用docker run-it-theimage运行它,并在容器中运行ps-eo-ppid、pid和args。使用以下选项时,将此输出与从ps接收的输出进行比较:
docker run-it theimage bash重建图像,但使用ENTRYPOINT/bin/bash并以两种方式运行使用CMD[“/bin/bash”]...
这样,您将很容易看到所有可能的方法之间的差异。
简而言之:
CMD设置默认命令和/或参数,当docker容器运行时,可以从命令行覆盖这些命令和/参数。ENTRYPOINT命令和参数不会从命令行覆盖。相反,所有命令行参数都将添加到ENTRYPOINT参数之后。
如果你需要更多的细节,或者想看到例子上的差异,有一篇博客文章将CMD和ENTRYPOINT与很多例子进行了全面比较https://codewithyury.com/docker-run-vs-cmd-vs-entrypoint/
我已经阅读了所有答案,我想总结一下,以便更好地理解以下内容:
首先,在容器中执行的整个命令包括两部分:命令和参数
ENTRYPOINT定义当容器已启动(用于命令)CMD指定传递给ENTRYPOINT的参数(用于参数)
在《Kubernetes In Action》一书中指出了一个重要的注意事项。(第7章)
尽管可以使用CMD指令指定命令要在运行映像时执行,正确的方法是执行通过ENTRYPOINT指令,并仅在以下情况下指定CMD希望定义默认参数。
你也可以阅读这篇文章,以简单的方式获得很好的解释