在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。

CMD的文档状态-

CMD的主要目的是为正在执行的容器提供默认值。

对于入口点:

ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。

那么,这两个命令之间有什么区别?


当前回答

我将把我的答案作为一个例子,1这样可以帮助你更好地理解其中的区别。

假设我们希望创建一个图像,该图像在启动时始终运行sleep命令。我们将创建自己的映像并指定一个新命令:

FROM ubuntu
CMD sleep 10

构建图像:

docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits

如果我们想改变秒数怎么办?我们必须更改Dockerfile,因为该值是硬编码的,或者通过提供不同的值来重写该命令:

docker run custom_sleep sleep 20

虽然这是可行的,但这不是一个好的解决方案,因为我们有一个冗余的“睡眠”命令。为什么冗余?因为容器的唯一目的是睡眠,所以必须显式指定睡眠命令有点尴尬。

现在,让我们尝试使用ENTRYPOINT指令:

FROM ubuntu
ENTRYPOINT sleep

此指令指定容器启动时将运行的程序。

现在我们可以运行:

docker run custom_sleep 20

默认值如何?嗯,你猜对了:

FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]

ENTRYPOINT是将要运行的程序,传递给容器的值将附加到该程序。

可以通过指定--ENTRYPOINT标志,后跟要使用的新入口点来覆盖ENTRYPOINT。

不是我的,我曾经看过一个提供了这个例子的教程

其他回答

代码中EntryPoint函数的注释

//入口/usr/sbin/nginx。//将入口点(默认为sh-c)设置为/usr/sbin/nginx。//将接受CMD作为/usr/sbin/nginx的参数。

文件中的另一个参考

您可以使用ENTRYPOINT的exec形式设置相当稳定的默认命令和参数,然后使用CMD设置更可能更改的其他默认值。

例子:

FROM ubuntu:14.04.3
ENTRYPOINT ["/bin/ping"]
CMD ["localhost", "-c", "2"]

Build:sudo docker Build-t ent_cmd。

CMD arguments are easy to override.

NO argument (sudo docker -it ent_cmd)                :  ping localhost 
argument    (sudo docker run -it ent_cmd google.com) :  ping google.com

.

To override EntryPoint argument, you need to supply entrypoint
sudo docker run -it --entrypoint="/bin/bash" ent_cmdd

附笔:在存在EntryPoint的情况下,CMD将保存要馈送到EntryPoint的参数。如果没有EntryPoint,CMD将是将要运行的命令。

CMD:

CMD[“executable”,“param1”,“param2”]:[“executible”,”param1“,”param2“]是第一个进程。CMD命令param1 param2:/bin/sh-c CMD命令param1 param2是第一个进程。CMD命令param1 param2从第一个进程分叉。CMD[“param1”,“param2”]:此表单用于为ENTRYPOINT提供默认参数。

ENTRYPOINT(以下列表不考虑CMD和ENTRYPOINT一起使用的情况):

ENTRYPOINT[“executable”,“param1”,“param2”]:[“executible”,”param1“,”param2“]是第一个进程。ENTRYPOINT命令param1 param2:/bin/sh-c命令param1 param2是第一个进程。命令param1 param2从第一个进程分叉。

正如creack所说,CMD是第一个开发的。然后,ENTRYPOINT被开发用于更多的定制。由于它们不是一起设计的,CMD和ENTRYPOINT之间存在一些功能重叠,这常常会让人感到困惑。

这个公认的答案在解释历史方面非常棒。我发现这张表很好地解释了“CMD和ENTRYPOINT如何交互”的官方文档:

我已经阅读了所有答案,我想总结一下,以便更好地理解以下内容:

首先,在容器中执行的整个命令包括两部分:命令和参数

ENTRYPOINT定义当容器已启动(用于命令)CMD指定传递给ENTRYPOINT的参数(用于参数)

在《Kubernetes In Action》一书中指出了一个重要的注意事项。(第7章)

尽管可以使用CMD指令指定命令要在运行映像时执行,正确的方法是执行通过ENTRYPOINT指令,并仅在以下情况下指定CMD希望定义默认参数。

你也可以阅读这篇文章,以简单的方式获得很好的解释

我想以轻松的方式区分CMD、RUN和ENTRYPOINT之间的差异。

让我们以节点的npm init为例。

命令:

假设下面是我们在dockerfile中添加的初始命令

CMD [ "npm", "init" ]

现在,如果我运行docker,运行-t node npm install

它将覆盖dockerfile中的npm init命令。

CMD [ "npm", "init" ] This will become  CMD [ "npm", "install" ]

它将执行npm install命令,而不是npm init,因为它会使用npm install。

现在,我们来谈谈

入口点:

假设在docker文件中添加了相同的命令,但使用ENTRYPOINT

ENTRYPOINT [ "npm", "init" ]

现在,如果我运行docker,运行-t节点安装

它将在dockerfile中附加npm init命令和npm install。

ENTRYPOINT [ "npm", "init" ] This will become  ENTRYPOINT [ "npm", "init", "install" ]

它将同时执行npm init和npm install命令。

总结如下:

RUN:这将在生成图像时执行。用于安装任何依赖项,如node_modules。例如RUN npm安装

CMD:要覆盖完整命令时使用

ENTRYPOINT:要附加一些附加命令时使用。