在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
当前回答
Dockerfile文件中提到的CMD命令可以通过docker run命令覆盖,而ENTRYPOINT不能覆盖。
其他回答
是的,这是个好问题。我还不完全理解,但是:
我知道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
Docker有一个默认入口点/bin/sh-c,但没有默认命令。
当你这样运行docker时:docker运行-i-t ubuntu bash入口点是默认的/bin/sh-c,图像是ubuntu,命令是bash。
该命令通过入口点运行。即,实际执行的是/bin/sh-cbash。这允许Docker依靠shell的解析器快速实现RUN。
后来,人们要求能够定制这个,所以引入了ENTRYPOINT和--ENTRYPOINT。
在上面的示例中,图像名称ubuntu之后的所有内容都是命令,并传递给入口点。当使用CMD指令时,它就像您在执行docker运行-i-t ubuntu<cmd>入口点的参数为<cmd>。
如果改为键入以下命令docker run-i-t ubuntu,也会得到相同的结果:bash shell将在容器中启动,因为在ubuntu Dockerfile中指定了默认CMD:CMD[“bash”]。
当一切都传递到入口点时,您可以从图像中获得非常好的行为@Jiri示例很好,它展示了如何将图像用作“二进制”。当使用[“/bin/cat”]作为入口点,然后执行docker运行img/etc/passwd时,您会发现,/etc/passwd是一个命令,并被传递到入口点,因此最终执行的结果只是/bin/cat/etc/passwd。
另一个示例是将任意cli作为入口点。例如,如果您有一个redis映像,而不是运行docker run redisig redis-H something-u to get key,您可以简单地使用ENTRYPOINT[“redis”,“-H”,“something”,“-u”,”toto“],然后像这样运行以获得相同的结果:docker run reisig get key。
我遇到了这个问题,一开始我发现老实说,这真的很令人困惑,我认为这种困惑来自于使用“CMD”一词,因为事实上,那里的东西充当了论据。所以挖了一点后,我明白了它是如何工作的。基本上:
ENTRYPOINT-->此处指定的是容器启动时要执行的命令。如果省略此定义,docker将使用/bin/sh-cbash来运行容器。
CMD-->这些是附加到ENTRYPOINT的参数,除非用户指定了一些自定义参数,即:docker run ubuntu<custom_CMD>在这种情况下,docker将运行ENTRYPOINT<custom_CMD>,而不是附加在CMD部分的图像上指定的内容。如果未指定ENTRYPOINT,则此处的内容将传递给/bin/sh-c,实际上作为启动容器时要执行的命令。
作为一切,最好用例子来解释发生了什么。因此,假设我使用以下规范Dockerfile创建了一个简单的docker映像:
From ubuntu
ENTRYPOINT ["sleep"]
然后我通过运行以下命令来构建它:
docker build . -t testimg
这将创建一个容器,每次运行时它都会休眠。所以,如果我按如下方式运行:
docker run testimg
我会得到以下信息:
sleep: missing operand
Try 'sleep --help' for more information.
这是因为入口点是需要参数的“sleep”命令。为了解决这个问题,我只需要提供睡眠量:
docker run testimg 5
这将正确运行,因此容器将运行,休眠5秒并退出。正如我们在这个示例中看到的,docker只是将图像名称后面的内容添加到入口点二进制docker runtestimg<my_cmd>。如果我们想将默认值(默认参数)传递给入口点,会发生什么?在这种情况下,我们只需要在CMD部分中指定它,例如:
From ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]
在这种情况下,如果用户没有传递任何参数,容器将使用默认值(10)并将其传递给入口点睡眠。
现在,让我们只使用CMD并省略ENTRYPOINT定义:
FROM ubuntu
CMD ["sleep", "5"]
如果我们重建并运行此图像,它将基本休眠5秒。
总之,您可以使用ENTRYPOINT使容器充当可执行文件。您可以使用CMD为入口点提供默认参数,或者在启动容器时运行自定义命令,该命令可以由用户从外部重写。
•Dockerfile应至少指定一条CMD或ENTRYPOINT指令
•仅使用Dockerfile中的最后一个CMD和ENTRYPOINT
•将容器用作可执行文件时,应定义ENTRYPOINT
•您应该使用CMD指令来定义默认参数定义为ENTRYPOINT的命令或用于在容器
•使用替代参数运行容器时,CMD将被覆盖
•ENTRYPOINT设置每次容器是使用图像创建的
•如果您将ENTRYPOINT与CMD结合,则可以从CMD中删除可执行文件并且只留下将传递给ENTRYPOINT的参数
•ENTRYPOINT的最佳用途是设置图像的主命令,允许映像要像运行该命令一样运行(然后使用CMD作为默认值标志)
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/