我对何时应该使用CMDRUN感到困惑。例如,要执行bash / shell命令(即ls -la),我将始终使用CMD,或者是否存在使用RUN的情况?试图了解有关这两个类似的Dockerfile指令的最佳实践。

评论

docs.microsoft.com/en-us/virtualization/windowscontainers/…

#1 楼

RUN是映像构建步骤,在执行RUN命令后,容器的状态将提交到容器映像。一个Dockerfile可以具有许多RUN步骤,这些步骤彼此叠加以构建映像。

CMD是启动构建映像时默认情况下容器执行的命令。 Dockerfile将仅使用最终定义的CMD。使用CMD启动容器时,可以覆盖docker run $image $other_command

ENTRYPOINT也与CMD密切相关,可以修改容器启动图像的方式。

评论


您需要执行所有RUN来设置您的环境,并且(仅)CMD启动了在您的容器中运行的进程,例如,对于nginx,请从github.com/nginxinc/docker-nginx/blob/中提取…,您会看到CMD [ “ nginx”,“-g”,“守护程序关闭”;]]

–user2915097
16年5月26日14:00

“一个Dockerfile只能有一个CMD”-从技术上讲不是正确的,但实际上除一个以外的所有内容都将被忽略。请参阅GingerBeer的答案。

– Colm Bhandal
20-4-19上午10:42

“ Dockerfile将仅使用定义的最终CMD”?实际上,最终定义的CMD将在启动映像时用作容器,对吗?

–张保罗
20-05-29在13:19

是@paulcheung,将dockerfile中的最终命令写入该映像,并且该命令是容器在您启动生成的映像时默认执行的命令。

–马特
20-05-31在23:35

#2 楼

RUN-在构建docker映像时触发命令。

CMD-在启动创建的docker映像时触发命令。

#3 楼

我发现本文对理解它们之间的区别非常有帮助:

RUN-
RUN指令允许您安装应用程序和所需的程序包。它会在当前图像的顶部执行任何命令
,并通过提交结果来创建新层。通常,您会在Dockerfile中找到多个RUN指令。

CMD-
CMD指令允许您设置默认命令,只有当您执行该命令时,它才会被执行
在不指定命令的情况下运行容器。
如果Docker容器通过命令运行,则默认命令将被忽略。如果Dockerfile具有多个CMD指令,则除最后一个
以外的所有CMD指令都将被忽略。

#4 楼

运行-安装Python,您的容器现在已将python刻录到其映像中
CMD-python hello.py,运行您喜欢的脚本

评论


CMD-安装Python,我的容器现在没有列出烧入其图像的python吗?

–卡洛斯·丰特斯
18-10-23在3:40

RUN将创建python的图像层,CMD将仅执行命令而不创建图像

– Rohit Salecha
18-10-25在13:25

#5 楼

RUN命令:
在构建映像时,RUN命令将基本上执行默认命令。它还将提交映像更改以进行下一步。

可以有多个RUN命令,以帮助构建新映像。

CMD命令:
CMD命令将为新容器设置默认命令。这不会在构建时执行。

如果docker文件具有多个1个CMD命令,则除最后一个命令外,所有命令均被忽略。因为此命令将不执行任何操作,而只是设置默认命令。

#6 楼


注意:不要将RUN与CMD混淆。 RUN实际上会运行命令,并且
提交结果; CMD在生成时不执行任何操作,但
指定映像的预期命令。


来自docker文件参考

https:// docs.docker.com/engine/reference/builder/#cmd

#7 楼

RUN:可以很多,并且在构建过程中使用,例如安装多个库

CMD:只能有1,这是您的执行起点(例如["npm", "start"]["node", "app.js"]

#8 楼

现有的答案涵盖了任何关注此问题的人所需要的大部分内容。因此,我只介绍CMD和RUN的一些特殊领域。

CMD:允许重复但很浪费

GingerBeer提出了一个重要的观点:您不会遇到任何错误如果您输入了多个CMD,则这样做很浪费。我想举一个例子:

FROM busybox
CMD echo "Executing CMD"
CMD echo "Executing CMD 2"


如果将其构建到图像中并在该图像中运行容器,那么按照GingerBeer的说法,只有最后CMD将受到关注。因此,该容器的输出将是:


执行CMD 2


我认为,“ CMD”设置单个全局变量用于生成的整个映像,因此,连续的“ CMD”语句将覆盖先前对该全局变量的所有写入操作,而在构建的最后一个映像中,最后一个要写入的变量将获胜。由于Dockerfile是从上到下依次执行的,因此我们知道最底层的CMD是获得最终“写入”的CMD(隐喻地说)。缓存

关于RUN的一个细微注意点是,即使有副作用,它也被视为纯函数,因此被缓存了。这意味着如果RUN具有一些不会改变结果映像的副作用,并且该映像已经被缓存,则RUN将不会再次执行,因此在后续构建中也不会发生副作用。例如,使用以下Dockerfile:

FROM busybox
RUN echo "Just echo while you work"


第一次运行它时,您将获得带有不同字母数字ID的此类输出:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Running in ed37d558c505
Just echo while you work
Removing intermediate container ed37d558c505
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest


请注意,echo语句已在上面执行。第二次运行它时,它将使用缓存,并且您在构建的输出中将看不到任何回声:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Using cache
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest


#9 楼

关于RUN和CMD的答案已经足够了。我只想在ENTRYPOINT上添加几句话。命令行参数可以覆盖CMD参数,而始终使用ENTRYPOINT参数。

本文是很好的信息来源。