否则,如果您想为通用目的制作图像,可以保留 ENTRYPOINT 未指定并使用 CMD ["/path/dedicated_command"] ,因为您可以通过向 docker run 提供参数来覆盖该设置 .
例如,如果您的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 --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命令 .
使用正常命令(如 docker run [args] )无法在运行时覆盖ENTRYPOINT . docker run [args] 末尾的 args 作为ENTRYPOINT的参数提供 . 通过这种方式,我们可以创建一个 container ,就像一个普通的二进制文件,如 ls .
9 回答
ENTRYPOINT
指定在容器启动时始终执行的命令 .CMD
指定将被提供给ENTRYPOINT
的参数 .如果您想制作专用于特定命令的图像,您将使用
ENTRYPOINT ["/path/dedicated_command"]
否则,如果您想为通用目的制作图像,可以保留
ENTRYPOINT
未指定并使用CMD ["/path/dedicated_command"]
,因为您可以通过向docker run
提供参数来覆盖该设置 .例如,如果您的Dockerfile是:
不带任何参数运行映像将ping本地主机:
现在,使用参数运行图像将ping参数:
为了比较,如果您的Dockerfile是:
不带任何参数运行映像将ping本地主机:
但是使用参数运行图像将运行参数:
有关更多详细信息,请参阅Brian DeHamer的这篇文章:https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/
Docker有一个默认入口点
/bin/sh -c
但没有默认命令 .当你像这样运行docker时:
docker run -i -t ubuntu bash
,入口点是默认的/bin/sh -c
,图像是ubuntu
,命令是bash
.该命令通过入口点运行 . 即,执行的实际内容是
/bin/sh -c bash
. 这允许Docker依靠shell的解析器快速实现RUN
.后来,人们要求能够自定义它,因此引入了
ENTRYPOINT
和--entrypoint
.在上面的示例中
ubuntu
之后的所有内容都是命令并传递给入口点 . 使用CMD
指令时,就像你在做docker run -i -t ubuntu <cmd>
一样 .<cmd>
将是入口点的参数 .如果您改为输入此命令
docker run -i -t ubuntu
,也会得到相同的结果 . 您仍将在容器中启动bash shell,因为ubuntu Dockerfile指定了默认CMD:CMD ["bash"]
当所有内容都传递到入口点时,您可以从图像中获得非常好的行为 . @Jiri示例很好,它显示了如何将图像用作"binary" . 当使用
["/bin/cat"]
作为入口点然后执行docker run img /etc/passwd
时,你得到它,/etc/passwd
是命令并传递给入口点,因此最终结果执行只是/bin/cat /etc/passwd
.另一个例子是将任何cli作为入口点 . 例如,如果你有一个redis图像,而不是运行
docker run redisimg redis -H something -u toto get key
,你可以简单地使用ENTRYPOINT ["redis", "-H", "something", "-u", "toto"]
,然后像这样运行相同的结果:docker run redisimg get key
.是的,这是一个很好的问题 . 我完全不了解它,但是:
我知道
ENTRYPOINT
是正在执行的二进制文件 . 您可以通过--entrypoint =“”覆盖入口点 .CMD是容器的默认参数 . 如果没有入口点,则default参数是执行的命令 . 使用入口点,cmd作为参数传递给入口点 . 您可以使用入口点模拟命令 .
因此,主要优点是使用入口点可以将参数(cmd)传递给容器 . 要实现此目的,您需要同时使用:
和
然后你可以使用:
简而言之:
CMD设置默认命令和/或参数,当docker容器运行时,可以从命令行覆盖它们 .
ENTRYPOINT命令和参数不会从命令行覆盖 . 相反,所有命令行参数将在ENTRYPOINT参数之后添加 .
如果您需要更多详细信息或想在示例中看到差异,那么有一篇博文全面地比较了CMD和ENTRYPOINT以及大量示例 - http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/
CMD:
CMD ["executable","param1","param2"]
:["executable","param1","param2"]
是第一个进程 .CMD command param1 param2
:/bin/sh -c CMD command param1 param2
是第一个进程 .CMD command param1 param2
是从第一个进程分叉的 .CMD ["param1","param2"]
:此表单用于为ENTRYPOINT
提供默认参数 .ENTRYPOINT(以下列表不考虑CMD和ENTRYPOINT一起使用的情况):
ENTRYPOINT ["executable", "param1", "param2"]
:["executable", "param1", "param2"]
是第一个进程 .ENTRYPOINT command param1 param2
:/bin/sh -c command param1 param2
是第一个进程 .command param1 param2
是从第一个进程分叉的 .正如creack所说,CMD是第一个开发的 . 然后开发了ENTRYPOINT以进行更多定制 . 由于它们不是一起设计的,因此CMD和ENTRYPOINT之间存在一些功能重叠,这常常让人感到困惑 .
接受的答案很棒,可以解释历史 . 我发现这张表很好地解释了它official doc on 'how CMD and ENTRYPOINT interact':
关于code中的EntryPoint函数的评论
文件的另一个参考
Example:
构建:sudo docker build -t ent_cmd .
.
p.s:在EntryPoint存在的情况下,CMD将保留参与EntryPoint的参数 . 在没有EntryPoint的情况下,CMD将成为将要运行的命令 .
CMD和ENTRYPOINT之间的区别 by intuition :
ENTRYPOINT:容器启动时运行的命令 .
CMD:在容器启动时运行的命令或ENTRYPOINT的参数(如果已指定) .
是的,它正在混淆 .
运行docker run时,您可以覆盖其中任何一个 .
CMD和ENTRYPOINT之间的区别 by example :
更多关于
CMD
和ENTRYPOINT
之间的区别:docker run
的参数如/ bin / bash会覆盖我们在Dockerfile中编写的任何CMD命令 .使用正常命令(如
docker run [args]
)无法在运行时覆盖ENTRYPOINT .docker run [args]
末尾的args
作为ENTRYPOINT的参数提供 . 通过这种方式,我们可以创建一个container
,就像一个普通的二进制文件,如ls
.所以CMD可以作为ENTRYPOINT的默认参数,然后我们可以从[args]覆盖CMD args .
可以使用
--entrypoint
覆盖ENTRYPOINT .根据docker docs,
下表显示 what command is executed for different ENTRYPOINT / CMD combinations :