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

CMD的文档状态-

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

对于入口点:

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

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


当前回答

我想以轻松的方式区分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:要附加一些附加命令时使用。

其他回答

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

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

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

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

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

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

是的,这是个好问题。我还不完全理解,但是:

我知道ENTRYPOINT是正在执行的二进制文件。可以通过--entrypoint=“”覆盖entrypoint。

docker run -t -i --entrypoint="/bin/bash" ubuntu

CMD是容器的默认参数。如果没有入口点,默认参数是执行的命令。使用entrypoint,cmd将作为参数传递给entryppoint。您可以使用入口点模拟命令。

# no entrypoint
docker run ubuntu /bin/cat /etc/passwd

# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd

所以,主要优点是使用entrypoint可以将参数(cmd)传递给容器。要做到这一点,您需要同时使用:

# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]

and

docker build -t=cat .

那么您可以使用:

docker run cat /etc/passwd
#              ^^^^^^^^^^^
#                   CMD
#          ^^^      
#          image (tag)- using the default ENTRYPOINT

有一些很好的答案。我想通过每个文档的演示来解释

CMD定义容器的默认命令和/或参数。如果您需要用户可以轻松覆盖的默认命令,则最好使用CMD指令。如果Dockerfile有多个CMD,它只应用最后一个CMD中的指令。当您想要定义具有特定可执行文件的容器时,首选ENTRYPOINT。

除非添加--ENTRYPOINT标志,否则无法在启动容器时重写ENTRYPOINT。

命令

Docker文件

  FROM centos:8.1.1911

  CMD ["echo", "Hello Docker"]

运行结果

$ sudo docker run <image-id>
Hello Docker
$ sudo docker run <image-id> hostname   # hostname is exec to override CMD
244be5006f32

入口点

Docker文件

  FROM centos:8.1.1911

  ENTRYPOINT ["echo", "Hello Docker"]

运行结果

$ sudo docker run <image-id>
Hello Docker
$ sudo docker run <image-id> hostname   # hostname as parameter to exec
Hello Docker hostname

在许多情况下,将CMD和ENTRYPOINT结合起来是Docker容器的最佳解决方案。在这种情况下,可执行文件使用ENTRYPOINT定义,而CMD指定默认参数。

Docker文件

  FROM centos:8.1.1911

  ENTRYPOINT ["echo", "Hello"]
  CMD ["Docker"]

运行结果

$ sudo docker run <image-id>
Hello Docker
$ sudo docker run <image-id> Ben
Hello Ben

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之间存在一些功能重叠,这常常会让人感到困惑。

Dockerfile文件中提到的CMD命令可以通过docker run命令覆盖,而ENTRYPOINT不能覆盖。