在Dockerfile中,有两个命令与我类似:CMD和ENTRYPOINT。但我想它们之间有一个(微妙的)区别——否则,对同一件事使用两个命令是没有意义的。

CMD的文档状态-

CMD的主要目的是为正在执行的容器提供默认值。

对于入口点:

ENTRYPOINT帮助您配置可以作为可执行文件运行的容器。

那么,这两个命令之间有什么区别?


当前回答

Dockerfile最佳实践的官方文档很好地解释了这些差异。Dockerfile最佳实践

CMD:

CMD指令应用于运行映像中包含的软件以及任何参数。CMD几乎应始终以CMD[“executable”,“param1”,“param2”…]的形式使用。因此,如果映像用于服务,例如Apache和Rails,则可以运行类似CMD[“apache2”,“-DFOREGROUND”]的命令。实际上,对于任何基于服务的图像,都建议使用这种形式的说明。

入口点:

ENTRYPOINT的最佳用法是设置映像的主命令,允许该映像像运行该命令一样运行(然后使用CMD作为默认标志)。

其他回答

简而言之:

CMD设置默认命令和/或参数,当docker容器运行时,可以从命令行覆盖这些命令和/参数。ENTRYPOINT命令和参数不会从命令行覆盖。相反,所有命令行参数都将添加到ENTRYPOINT参数之后。

如果你需要更多的细节,或者想看到例子上的差异,有一篇博客文章将CMD和ENTRYPOINT与很多例子进行了全面比较https://codewithyury.com/docker-run-vs-cmd-vs-entrypoint/

Dockerfile最佳实践的官方文档很好地解释了这些差异。Dockerfile最佳实践

CMD:

CMD指令应用于运行映像中包含的软件以及任何参数。CMD几乎应始终以CMD[“executable”,“param1”,“param2”…]的形式使用。因此,如果映像用于服务,例如Apache和Rails,则可以运行类似CMD[“apache2”,“-DFOREGROUND”]的命令。实际上,对于任何基于服务的图像,都建议使用这种形式的说明。

入口点:

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终端

•Dockerfile应至少指定一条CMD或ENTRYPOINT指令

•仅使用Dockerfile中的最后一个CMD和ENTRYPOINT

•将容器用作可执行文件时,应定义ENTRYPOINT

•您应该使用CMD指令来定义默认参数定义为ENTRYPOINT的命令或用于在容器

•使用替代参数运行容器时,CMD将被覆盖

•ENTRYPOINT设置每次容器是使用图像创建的

•如果您将ENTRYPOINT与CMD结合,则可以从CMD中删除可执行文件并且只留下将传递给ENTRYPOINT的参数

•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