Dockerfile中RUN和CMD的区别

bqujaahr  于 2023-05-06  发布在  Docker
关注(0)|答案(9)|浏览(246)

我很困惑什么时候应该使用CMDRUN。例如,要执行bash/shell命令(即ls -la)我会一直使用CMD,或者在某些情况下我会使用RUN?试图理解这两个类似的Dockerfile指令的最佳实践。

gijlo24d

gijlo24d1#

RUN是映像构建步骤,RUN命令后容器的状态将提交到容器映像。一个Dockerfile可以有许多RUN步骤,这些步骤一个在另一个之上,以构建镜像。
CMD是启动构建映像时容器默认执行的命令。Dockerfile将只使用最终定义的CMD。当用docker run $image $other_command启动容器时,CMD可以被覆盖。
ENTRYPOINT也与CMD密切相关,并且可以修改从映像启动容器时解释CMD的方式。

noj0wjuj

noj0wjuj2#

RUN-在我们构建docker镜像时触发命令。
CMD-命令在我们启动创建的docker镜像时触发。

2jcobegt

2jcobegt3#

我发现this文章对理解它们之间的区别很有帮助:

RUN- RUN指令用于安装应用程序及其所需的包。它在当前图像上执行任何命令,并通过提交结果创建一个新层。通常你会在一个Dockerfile中发现多个RUN指令。
CMD- CMD指令可以设置默认命令,只有在不指定命令的情况下运行容器时才会执行。如果Docker容器使用命令运行,则默认命令将被忽略。如果Dockerfile有多条CMD指令,则除最后一条以外的所有指令

CMD指令被忽略。

oiopk7p5

oiopk7p54#

现有的答案涵盖了任何人在研究这个问题时所需要的大部分内容。因此,我将只涵盖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有一些副作用不会改变结果图像,并且该图像已经被缓存,那么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语句。第二次运行它时,它使用该高速缓存,并且您不会在构建的输出中看到任何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
ki1q1bka

ki1q1bka5#

RUN-安装Python,您的容器现在已将python烧入其映像
CMD- pythonhello.py,运行你喜欢的脚本

p1iqtdky

p1iqtdky6#

注意:不要将RUN与CMD混淆。RUN实际上运行一个命令并提交结果;CMD在构建时不执行任何操作,但为映像指定预期的命令。
从docker文件引用
https://docs.docker.com/engine/reference/builder/#cmd

xqk2d5yq

xqk2d5yq7#

RUN命令:RUN命令将基本上执行默认命令,当我们构建映像时。它还将为下一步提交图像更改。
可以有多个RUN命令,以帮助构建新映像的过程。
CMD命令:CMD命令将只为新容器设置默认命令。这不会在构建时执行。
如果一个docker文件有超过1个CMD命令,那么除了最后一个命令之外,所有的命令都会被忽略。因为此命令不会执行任何操作,而只是设置默认命令。

hiz5n14c

hiz5n14c8#

RUN:可以有很多个,用于build流程,例如安装多个库
CMD:只能有1,这是您的执行起始点(例如["npm", "start"]["node", "app.js"]

j8ag8udp

j8ag8udp9#

RUNCMD的答案已经足够了。我只想对ENTRYPOINT补充几句。CMD参数可以被命令行参数覆盖,而ENTRYPOINT参数始终使用。

This article是一个很好的信息来源。

相关问题