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

CMD的文档状态-

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

对于入口点:

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

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


当前回答

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

其他回答

•Dockerfile应至少指定一条CMD或ENTRYPOINT指令

•仅使用Dockerfile中的最后一个CMD和ENTRYPOINT

•将容器用作可执行文件时,应定义ENTRYPOINT

•您应该使用CMD指令来定义默认参数定义为ENTRYPOINT的命令或用于在容器

•使用替代参数运行容器时,CMD将被覆盖

•ENTRYPOINT设置每次容器是使用图像创建的

•如果您将ENTRYPOINT与CMD结合,则可以从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的参数(如果指定)。

是的,这令人困惑。

在运行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重写。

ENTRYPOINT指定在容器启动时始终执行的命令。

CMD指定将被馈送到ENTRYPOINT的参数。

如果要使图像专用于特定命令,则将使用ENTRYPOINT[“/path/dessisted_command”]

否则,如果您想为通用目的生成图像,可以不指定ENTRYPOINT,使用CMD[“/path/dessisted_command”],因为您可以通过为docker运行提供参数来覆盖设置。

例如,如果Dockerfile是:

FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]

在没有任何参数的情况下运行映像将ping本地主机:

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.096 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.088 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.088 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.088/0.091/0.096/0.000 ms

现在,运行带有参数的图像将ping该参数:

$ docker run -it test google.com
PING google.com (173.194.45.70): 48 data bytes
56 bytes from 173.194.45.70: icmp_seq=0 ttl=55 time=32.583 ms
56 bytes from 173.194.45.70: icmp_seq=2 ttl=55 time=30.327 ms
56 bytes from 173.194.45.70: icmp_seq=4 ttl=55 time=46.379 ms
^C--- google.com ping statistics ---
5 packets transmitted, 3 packets received, 40% packet loss
round-trip min/avg/max/stddev = 30.327/36.430/46.379/7.095 ms

作为比较,如果Dockerfile是:

FROM debian:wheezy
CMD ["/bin/ping", "localhost"]

在没有任何参数的情况下运行映像将ping本地主机:

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.076 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.076/0.084/0.090/0.000 ms

但使用参数运行图像将运行参数:

docker run -it test bash
root@e8bb7249b843:/#

有关更多详细信息,请参阅Brian DeHamer的这篇文章:https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-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:要附加一些附加命令时使用。