在Dockerfiles中有两个看起来与我类似的命令:CMD
和ENTRYPOINT
.但是我猜它们之间存在着一种(微妙的?)差异 - 否则对于同样的事情来说两个命令就没有任何意义.
文档说明了 CMD
CMD的主要目的是为执行容器提供默认值.
并为ENTRYPOINT
:
ENTRYPOINT可帮助您配置可作为可执行文件运行的容器.
那么,这两个命令之间的区别是什么?
cre*_*ack 1561
Docker有一个默认入口点,/bin/sh -c
但它没有默认命令.
当您像这样运行docker时:
docker run -i -t ubuntu bash
入口点是默认值/bin/sh -c
,图像是ubuntu
,命令是bash
.
该命令通过入口点运行.即,实际执行的事情是/bin/sh -c bash
.这使得Docker可以RUN
依靠shell的解析器快速实现.
后来,人们要求能够自定义这个,所以ENTRYPOINT
并且--entrypoint
被介绍了.
ubuntu
上面示例中的所有内容都是命令,并传递给入口点.使用该CMD
指令时,就像您正在做的那样docker run -i -t ubuntu <cmd>
.<cmd>
将是入口点的参数.
如果您改为输入此命令,也会得到相同的结果docker run -i -t ubuntu
.你仍然会在容器中启动一个bash shell,因为ubuntu Dockerfile指定了一个默认的CMD:CMD ["bash"]
当所有内容都传递到入口点时,您可以从图像中获得非常好的行为.@Jiri示例很好,它显示了如何将图像用作"二进制".当["/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
.
Dai*_*shi 530
该ENTRYPOINT
规定将始终容器启动时执行的命令.
该CMD
指定参数,将被输送到ENTRYPOINT
.
如果您想制作专用于您将使用的特定命令的图像 ENTRYPOINT ["/path/dedicated_command"]
否则,如果您想为一般目的制作图像,您可以保留ENTRYPOINT
未指定并使用,CMD ["/path/dedicated_command"]
因为您可以通过提供参数来覆盖设置docker run
.
例如,如果您的Dockerfile是:
FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]
Run Code Online (Sandbox Code Playgroud)
不带任何参数运行映像将ping localhost:
$ 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
Run Code Online (Sandbox Code Playgroud)
现在,使用参数运行图像将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
Run Code Online (Sandbox Code Playgroud)
为了比较,如果您的Dockerfile是:
FROM debian:wheezy
CMD ["/bin/ping", "localhost"]
Run Code Online (Sandbox Code Playgroud)
不带任何参数运行映像将ping localhost:
$ 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
Run Code Online (Sandbox Code Playgroud)
但是使用参数运行图像将运行参数:
docker run -it test bash
root@e8bb7249b843:/#
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅Brian DeHamer的这篇文章:https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/
Raf*_*sin 200
CMD和ENTRYPOINT指令都定义了在运行容器时执行的命令.很少有规则描述他们的合作.
- Dockerfile应至少指定一个
CMD
或多个ENTRYPOINT
命令.ENTRYPOINT
应该在将容器用作可执行文件时定义.CMD
应该用作定义ENTRYPOINT
命令的默认参数或在容器中执行ad-hoc命令的方法.CMD
在使用备用参数运行容器时将覆盖.
下表显示了针对不同ENTRYPOINT
/ CMD
组合执行的命令:
- No ENTRYPOINT
????????????????????????????????????????????????????????????
? No CMD ? error, not allowed ?
????????????????????????????????????????????????????????????
? CMD [“exec_cmd”, “p1_cmd”] ? exec_cmd p1_cmd ?
????????????????????????????????????????????????????????????
? CMD [“p1_cmd”, “p2_cmd”] ? p1_cmd p2_cmd ?
????????????????????????????????????????????????????????????
? CMD exec_cmd p1_cmd ? /bin/sh -c exec_cmd p1_cmd ?
????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
- ENTRYPOINT exec_entry p1_entry
?????????????????????????????????????????????????????????????????
? No CMD ? /bin/sh -c exec_entry p1_entry ?
?????????????????????????????????????????????????????????????????
? CMD [“exec_cmd”, “p1_cmd”] ? /bin/sh -c exec_entry p1_entry ?
?????????????????????????????????????????????????????????????????
? CMD [“p1_cmd”, “p2_cmd”] ? /bin/sh -c exec_entry p1_entry ?
?????????????????????????????????????????????????????????????????
? CMD exec_cmd p1_cmd ? /bin/sh -c exec_entry p1_entry ?
?????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
- ENTRYPOINT [“exec_entry”, “p1_entry”]
????????????????????????????????????????????????????????????????????????????????
? No CMD ? exec_entry p1_entry ?
????????????????????????????????????????????????????????????????????????????????
? CMD [“exec_cmd”, “p1_cmd”] ? exec_entry p1_entry exec_cmd p1_cmd ?
????????????????????????????????????????????????????????????????????????????????
? CMD [“p1_cmd”, “p2_cmd”] ? exec_entry p1_entry p1_cmd p2_cmd ?
????????????????????????????????????????????????????????????????????????????????
? CMD exec_cmd p1_cmd ? exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd ?
????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
Jir*_*iri 163
是的,这是个好问题.我还不完全理解它,但是:
我知道这ENTRYPOINT
是正在执行的二进制文件.您可以通过--entrypoint =""覆盖入口点.
docker run -t -i --entrypoint="/bin/bash" ubuntu
Run Code Online (Sandbox Code Playgroud)
CMD是容器的默认参数.如果没有入口点,则default参数是执行的命令.使用入口点,cmd作为参数传递给入口点.您可以使用入口点模拟命令.
# no entrypoint
docker run ubuntu /bin/cat /etc/passwd
# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd
Run Code Online (Sandbox Code Playgroud)
因此,主要优点是使用入口点可以将参数(cmd)传递给容器.要实现此目的,您需要同时使用:
# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]
Run Code Online (Sandbox Code Playgroud)
和
docker build -t=cat .
Run Code Online (Sandbox Code Playgroud)
然后你可以使用:
docker run cat /etc/passwd
# ^^^^^^^^^^^
# CMD
# ^^^
# image (tag)- using the default ENTRYPOINT
Run Code Online (Sandbox Code Playgroud)
Tom*_*vid 42
直觉 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
Run Code Online (Sandbox Code Playgroud)
更多关于CMD
和之间的区别ENTRYPOINT
:
参数docker run
例如/ bin/bash的覆盖我们Dockerfile写任何CMD命令.
使用常规命令(例如)时,无法在运行时覆盖ENTRYPOINT docker run [args]
.所述args
在端部docker run [args]
被设置为参数入口点.通过这种方式,我们可以创建一个container
像普通二进制文件一样的东西ls
.
所以CMD可以作为ENTRYPOINT的默认参数,然后我们可以从[args]覆盖CMD args.
ENTRYPOINT可以覆盖--entrypoint
.
upi*_*tau 36
简而言之:
如果您需要更多详细信息或想在示例中看到差异,可以通过大量示例全面比较CMD和ENTRYPOINT的博客文章 - http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/
zan*_*ngw 28
有一些很好的答案。我想通过每个文档的演示来解释它
CMD
定义容器的默认命令和/或参数。如果您需要用户可以轻松覆盖的默认命令,则 CMD 是最好使用的指令。如果一个 Dockerfile 有多个 CMD,它只会应用最后一个的指令。ENTRYPOINT
当您想定义具有特定可执行文件的容器时,首选。ENTRYPOINT
除非添加--entrypoint
标志,否则在启动容器时 不能覆盖 an 。
Docker 文件
FROM centos:8.1.1911
CMD ["echo", "Hello Docker"]
Run Code Online (Sandbox Code Playgroud)
运行结果
$ sudo docker run <image-id>
Hello Docker
$ sudo docker run <image-id> hostname # hostname is exec to override CMD
244be5006f32
Run Code Online (Sandbox Code Playgroud)
Docker 文件
FROM centos:8.1.1911
ENTRYPOINT ["echo", "Hello Docker"]
Run Code Online (Sandbox Code Playgroud)
运行结果
$ sudo docker run <image-id>
Hello Docker
$ sudo docker run <image-id> hostname # hostname as parameter to exec
Hello Docker hostname
Run Code Online (Sandbox Code Playgroud)
Docker 文件
FROM centos:8.1.1911
ENTRYPOINT ["echo", "Hello"]
CMD ["Docker"]
Run Code Online (Sandbox Code Playgroud)
运行结果
$ sudo docker run <image-id>
Hello Docker
$ sudo docker run <image-id> Ben
Hello Ben
Run Code Online (Sandbox Code Playgroud)
Mah*_*rus 15
我想轻松区分CMD、RUN 和 ENTRYPOINT之间的差异。
\n让\xe2\x80\x99s 以节点的 npm init 为例。
\n命令:
\n让\xe2\x80\x99s 假设下面是我们在 dockerfile 中添加的初始命令
\nCMD [ "npm", "init" ]\n
Run Code Online (Sandbox Code Playgroud)\n现在,如果我跑docker run -t node npm install
它将覆盖 dockerfile 中的 npm init 命令。
\nCMD [ "npm", "init" ] This will become CMD [ "npm", "install" ]\n
Run Code Online (Sandbox Code Playgroud)\n它将执行该npm install
命令,而不是npm init
用 npm install 覆盖该命令。
现在,让\xe2\x80\x99s 谈谈
\n入口点 :
\n让\xe2\x80\x99s 假设在 docker 文件中添加相同的命令,但使用 ENTRYPOINT
\nENTRYPOINT [ "npm", "init" ]\n
Run Code Online (Sandbox Code Playgroud)\n现在,如果我跑docker run -t node install
它将在 dockerfile 中附加 npm init 命令和 npm install。
\nENTRYPOINT [ "npm", "init" ] This will become ENTRYPOINT [ "npm", "init", "install" ]\n
Run Code Online (Sandbox Code Playgroud)\n它将执行 npm init 和 npm install 命令。
\n总结 :
\nRUN:这将在生成图像时执行。用于安装任何依赖项,例如node_modules。前任。RUN npm install
CMD :当您想要覆盖完整命令时使用
\nENTRYPOINT:当您想要附加一些附加命令时使用。
\nrka*_*ach 13
我遇到了这个问题,一开始我发现说实话真的很混乱,我认为这种混乱来自使用“CMD”这个词,因为实际上那里的内容充当了论点。所以在挖掘了一点之后,我明白了它是如何工作的。基本上:
ENTRYPOINT --> 您在此处指定的是容器启动时要执行的命令。如果您省略此定义,docker 将用于/bin/sh -c bash
运行您的容器。
CMD --> 这些是附加到 ENTRYPOINT的参数,除非用户指定一些自定义参数,即:docker run ubuntu <custom_cmd>
在这种情况下,docker 将运行而不是附加在 CMD 部分中的图像上指定的内容ENTRYPOINT <custom_cmd>
。如果未指定 ENTRYPOINT,这里的内容将被传递给/bin/sh -c
实际上作为启动容器时要执行的命令。
作为一切,最好通过示例来解释正在发生的事情。因此,假设我使用以下规范Dockerfile创建了一个简单的docker 镜像:
From ubuntu
ENTRYPOINT ["sleep"]
Run Code Online (Sandbox Code Playgroud)
然后我通过运行以下命令来构建它:
docker build . -t testimg
Run Code Online (Sandbox Code Playgroud)
这将创建一个每次运行时都会休眠的容器。所以如果我按如下方式运行它:
docker run testimg
Run Code Online (Sandbox Code Playgroud)
我会得到以下信息:
sleep: missing operand
Try 'sleep --help' for more information.
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为入口点是需要参数的“sleep”命令。所以为了解决这个问题,我只提供睡眠的数量:
docker run testimg 5
Run Code Online (Sandbox Code Playgroud)
这将正确运行,因此容器将运行,休眠 5 秒并退出。正如我们在这个例子中看到的,docker 只是将图像名称后面的内容附加到入口点 binary docker run testimg <my_cmd>
。如果我们想将默认值(默认参数)传递给入口点会发生什么?在这种情况下,我们只需要在CMD部分指定它,例如:
From ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如果用户不传递任何参数,容器将使用默认值 (10) 并将其传递给入口点 sleep。
现在让我们只使用 CMD 并省略 ENTRYPOINT 定义:
FROM ubuntu
CMD ["sleep", "5"]
Run Code Online (Sandbox Code Playgroud)
如果我们重建并运行这个镜像,它基本上会休眠 5 秒。
总而言之,您可以使用ENTRYPOINT使您的容器充当可执行文件。您可以使用CMD为入口点提供默认参数,或者在启动容器时运行自定义命令,该命令可由用户从外部覆盖。
Mar*_*oun 12
我将以示例1的方式添加答案,这可能有助于您更好地理解差异。
假设我们要创建一个在启动时始终运行sleep命令的映像。我们将创建自己的图像并指定一个新命令:
FROM ubuntu
CMD sleep 10
Run Code Online (Sandbox Code Playgroud)
现在,我们构建图像:
docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits
Run Code Online (Sandbox Code Playgroud)
如果要更改秒数怎么办?我们将不得不更改Dockerfile
值,因为该值在此处进行了硬编码,或者通过提供不同的值来覆盖该命令:
docker run custom_sleep sleep 20
Run Code Online (Sandbox Code Playgroud)
尽管这可行,但这不是一个好的解决方案,因为我们有一个多余的“ sleep”命令(容器的目的是sleep,因此必须显式指定该sleep
命令不是一个好习惯)。
现在让我们尝试使用以下ENTRYPOINT
指令:
docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits
Run Code Online (Sandbox Code Playgroud)
该指令指定在容器启动时将运行的程序。
现在我们可以运行:
docker run custom_sleep sleep 20
Run Code Online (Sandbox Code Playgroud)
那么默认值呢?好吧,你猜对了:
FROM ubuntu
ENTRYPOINT sleep
Run Code Online (Sandbox Code Playgroud)
的ENTRYPOINT
是将要运行的程序,并通过在容器上的值将被附加到它。
该ENTRYPOINT
可通过指定覆盖--entrypoint
标志,后面是要使用新的切入点。
不是我的,我曾经看过提供此示例的教程
小智 6
对代码中的 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"]
Run Code Online (Sandbox Code Playgroud)
构建: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
Run Code Online (Sandbox Code Playgroud)
.
To override EntryPoint argument, you need to supply entrypoint
sudo docker run -it --entrypoint="/bin/bash" ent_cmdd
Run Code Online (Sandbox Code Playgroud)
ps:在EntryPoint存在的情况下,CMD将保留参与EntryPoint的参数.在没有EntryPoint的情况下,CMD将成为将要运行的命令.
我已经阅读了所有答案,我想总结一下,以便乍一看更好地理解,如下所示:
首先,在容器中执行的整个命令包括两部分: 命令和 参数
ENTRYPOINT定义容器启动时调用的可执行文件(用于命令)
CMD指定传递给 ENTRYPOINT 的参数(用于参数)
在Kubernetes In Action一书中指出了一个关于它的重要说明。(第7章)
虽然可以使用CMD指令指定镜像运行时要执行的命令,但正确的方法是通过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
从第一个进程分叉。正如creak所说,CMD 是最先开发的。然后开发了 ENTRYPOINT 以进行更多定制。由于它们不是一起设计的,因此 CMD 和 ENTRYPOINT 之间存在一些功能重叠,这经常使人们感到困惑。
归档时间: |
|
查看次数: |
440852 次 |
最近记录: |