在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
当前回答
大多数人在这里都解释得很好,所以我不会重复所有的答案。但为了得到一个好的感觉,我建议自己通过查看容器中的流程来测试它。
创建一个小型Dockerfile,格式如下:
FROM ubuntu:latest
CMD /bin/bash
构建它,用docker run-it-theimage运行它,并在容器中运行ps-eo-ppid、pid和args。使用以下选项时,将此输出与从ps接收的输出进行比较:
docker run-it theimage bash重建图像,但使用ENTRYPOINT/bin/bash并以两种方式运行使用CMD[“/bin/bash”]...
这样,您将很容易看到所有可能的方法之间的差异。
其他回答
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之间存在一些功能重叠,这常常会让人感到困惑。
我将把我的答案作为一个例子,1这样可以帮助你更好地理解其中的区别。
假设我们希望创建一个图像,该图像在启动时始终运行sleep命令。我们将创建自己的映像并指定一个新命令:
FROM ubuntu
CMD sleep 10
构建图像:
docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits
如果我们想改变秒数怎么办?我们必须更改Dockerfile,因为该值是硬编码的,或者通过提供不同的值来重写该命令:
docker run custom_sleep sleep 20
虽然这是可行的,但这不是一个好的解决方案,因为我们有一个冗余的“睡眠”命令。为什么冗余?因为容器的唯一目的是睡眠,所以必须显式指定睡眠命令有点尴尬。
现在,让我们尝试使用ENTRYPOINT指令:
FROM ubuntu
ENTRYPOINT sleep
此指令指定容器启动时将运行的程序。
现在我们可以运行:
docker run custom_sleep 20
默认值如何?嗯,你猜对了:
FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]
ENTRYPOINT是将要运行的程序,传递给容器的值将附加到该程序。
可以通过指定--ENTRYPOINT标志,后跟要使用的新入口点来覆盖ENTRYPOINT。
不是我的,我曾经看过一个提供了这个例子的教程
我已经阅读了所有答案,我想总结一下,以便更好地理解以下内容:
首先,在容器中执行的整个命令包括两部分:命令和参数
ENTRYPOINT定义当容器已启动(用于命令)CMD指定传递给ENTRYPOINT的参数(用于参数)
在《Kubernetes In Action》一书中指出了一个重要的注意事项。(第7章)
尽管可以使用CMD指令指定命令要在运行映像时执行,正确的方法是执行通过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/
大多数人在这里都解释得很好,所以我不会重复所有的答案。但为了得到一个好的感觉,我建议自己通过查看容器中的流程来测试它。
创建一个小型Dockerfile,格式如下:
FROM ubuntu:latest
CMD /bin/bash
构建它,用docker run-it-theimage运行它,并在容器中运行ps-eo-ppid、pid和args。使用以下选项时,将此输出与从ps接收的输出进行比较:
docker run-it theimage bash重建图像,但使用ENTRYPOINT/bin/bash并以两种方式运行使用CMD[“/bin/bash”]...
这样,您将很容易看到所有可能的方法之间的差异。