在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。
CMD的文档状态-
CMD的主要目的是为正在执行的容器提供默认值。
对于入口点:
ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。
那么,这两个命令之间有什么区别?
当前回答
Dockerfile最佳实践的官方文档很好地解释了这些差异。Dockerfile最佳实践
CMD:
CMD指令应用于运行映像中包含的软件以及任何参数。CMD几乎应始终以CMD[“executable”,“param1”,“param2”…]的形式使用。因此,如果映像用于服务,例如Apache和Rails,则可以运行类似CMD[“apache2”,“-DFOREGROUND”]的命令。实际上,对于任何基于服务的图像,都建议使用这种形式的说明。
入口点:
ENTRYPOINT的最佳用法是设置映像的主命令,允许该映像像运行该命令一样运行(然后使用CMD作为默认标志)。
其他回答
是的,这是个好问题。我还不完全理解,但是:
我知道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
我已经阅读了所有答案,我想总结一下,以便更好地理解以下内容:
首先,在容器中执行的整个命令包括两部分:命令和参数
ENTRYPOINT定义当容器已启动(用于命令)CMD指定传递给ENTRYPOINT的参数(用于参数)
在《Kubernetes In Action》一书中指出了一个重要的注意事项。(第7章)
尽管可以使用CMD指令指定命令要在运行映像时执行,正确的方法是执行通过ENTRYPOINT指令,并仅在以下情况下指定CMD希望定义默认参数。
你也可以阅读这篇文章,以简单的方式获得很好的解释
通过从头开始重建OS映像(只需从头开始编写,并在dockerfile中使用COPY复制最小的文件系统),我了解到,
如果没有在dockerfile中指定ENTRYPOINT和CMD,docker将使用
/bin/sh -c
作为默认ENTRYPOINT,如果在docker文件中定义CMD或在运行容器时传递命令行参数(这将覆盖已定义的CMD),则将采用CMD。
假设您传递一个参数(或在dockerfile中定义CMD)ls,那么它将被馈送到ENTRYPOINT。即,
/bin/sh -c ls
/bin/sh-c将运行传递给它的任何参数。您将获得“ls”命令的输出,然后容器将退出。
ubuntu映像没有显式定义ENTRYPOINT,因此docker将使用/bin/sh-c,但包含CMD定义,即bash运行容器的以下命令,
docker container run -it ubuntu
Docker实际上使用ENTRYPOINT作为/bin/sh-c,然后使用bash为其提供数据最终运行的是
/bin/sh -c bash
它启动交互式bash终端(仅当如上所述指定了-i标志并可选地指定了-t以获得类似本地终端的体验时)
当您通过命令行提供参数时,bash将被替换为您传递的任何内容,输出将根据该内容,即
/bin/sh -c passed_argument
您可以定义自定义ENTRYPOINT,它将覆盖默认ENTRYPOINT,但随后需要相应地使用CMD。
对于dockerfile中的RUN命令,它不考虑定义的ENTRYPOINT和CMD,而是运行指定的命令,因为它们被提供给中间容器中的交互式bash终端
简而言之:
CMD设置默认命令和/或参数,当docker容器运行时,可以从命令行覆盖这些命令和/参数。ENTRYPOINT命令和参数不会从命令行覆盖。相反,所有命令行参数都将添加到ENTRYPOINT参数之后。
如果你需要更多的细节,或者想看到例子上的差异,有一篇博客文章将CMD和ENTRYPOINT与很多例子进行了全面比较https://codewithyury.com/docker-run-vs-cmd-vs-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"]
Build: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
.
To override EntryPoint argument, you need to supply entrypoint
sudo docker run -it --entrypoint="/bin/bash" ent_cmdd
附笔:在存在EntryPoint的情况下,CMD将保存要馈送到EntryPoint的参数。如果没有EntryPoint,CMD将是将要运行的命令。