简体   繁体   English

Dockerfile 中 RUN 和 CMD 的区别

[英]Difference between RUN and CMD in a Dockerfile

I'm confused about when should I use CMD vs RUN .我对什么时候应该使用CMDRUN感到困惑。 For example, to execute bash/shell commands (ie ls -la ) I would always use CMD or is there a situation where I would use RUN ?例如,要执行 bash/shell 命令(即ls -la ),我将始终使用CMD或者是否存在使用RUN Trying to understand the best practices about these two similar Dockerfile directives.试图了解关于这两个类似Dockerfile指令的最佳实践。

RUN is an image build step, the state of the container after a RUN command will be committed to the container image. RUN是一个镜像构建步骤, RUN命令后容器的状态将被提交到容器镜像。 A Dockerfile can have many RUN steps that layer on top of one another to build the image.一个 Dockerfile 可以有许多RUN步骤,这些步骤相互叠加以构建映像。

CMD is the command the container executes by default when you launch the built image. CMD是当您启动构建的镜像时容器默认执行的命令。 A Dockerfile will only use the final CMD defined. Dockerfile 将只使用最终定义的CMD The CMD can be overridden when starting a container with docker run $image $other_command .使用docker run $image $other_command启动容器时,可以覆盖CMD

ENTRYPOINT is also closely related to CMD and can modify the way a container starts an image.ENTRYPOINT也与CMD密切相关,可以修改容器启动镜像的方式。

RUN - command triggers while we build the docker image. RUN - 命令在我们构建 docker 镜像时触发。

CMD - command triggers while we launch the created docker image. CMD - 命令在我们启动创建的 docker 镜像时触发。

I found this article very helpful to understand the difference between them:我发现这篇文章非常有助于理解它们之间的区别:

RUN - RUN instruction allows you to install your application and packages required for it. RUN - RUN 指令允许您安装您的应用程序和所需的包。 It executes any commands on top of the current image and creates a new layer by committing the results.它在当前图像之上执行任何命令,并通过提交结果创建一个新层。 Often you will find multiple RUN instructions in a Dockerfile.通常,您会在 Dockerfile 中找到多个 RUN 指令。

CMD - CMD instruction allows you to set a default command, which will be executed only when you run container without specifying a command. CMD - CMD 指令允许您设置默认命令,该命令仅在您运行容器而不指定命令时执行。 If Docker container runs with a command, the default command will be ignored.如果 Docker 容器使用命令运行,则默认命令将被忽略。 If Dockerfile has more than one CMD instruction, all but last如果 Dockerfile 有一个以上的 CMD 指令,除了最后一条指令
CMD instructions are ignored. CMD 指令被忽略。

RUN - Install Python , your container now has python burnt into its image RUN - 安装 Python ,您的容器现在已将 Python烧录到其映像中
CMD - python hello.py , run your favourite script CMD - python hello.py ,运行你喜欢的脚本

The existing answers cover most of what anyone looking at this question would need.现有答案涵盖了查看此问题的任何人所需的大部分内容。 So I'll just cover some niche areas for CMD and RUN.所以我将只介绍 CMD 和 RUN 的一些利基领域。

CMD: Duplicates are Allowed but Wasteful CMD:允许重复但浪费

GingerBeer makes an important point: you won't get any errors if you put in more than one CMD - but it's wasteful to do so. GingerBeer 提出了一个重要观点:如果你输入多个 CMD,你不会得到任何错误 - 但这样做很浪费。 I'd like to elaborate with an example:我想用一个例子来详细说明:

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

If you build this into an image and run a container in this image, then as GingerBeer states, only the last CMD will be heeded.如果你将它构建到一个镜像中并在这个镜像中运行一个容器,那么正如 GingerBeer 所说,只有最后一个 CMD 会被注意。 So the output of that container will be:所以该容器的输出将是:

Executing CMD 2执行 CMD 2

The way I think of it is that "CMD" is setting a single global variable for the entire image that is being built, so successive "CMD" statements simply overwrite any previous writes to that global variable, and in the final image that's built the last one to write wins.我的想法是“CMD”正在为正在构建的整个图像设置一个全局变量,因此连续的“CMD”语句只是覆盖对该全局变量的任何先前写入,并且在构建的最终图像中最后一个写胜。 Since a Dockerfile executes in order from top to bottom, we know that the bottom-most CMD is the one gets this final "write" (metaphorically speaking).由于 Dockerfile 按从上到下的顺序执行,我们知道最底层的 CMD 是获得最后“写入”的那个(比喻地说)。

RUN: Commands May not Execute if Images are Cached RUN:如果图像被缓存,命令可能不会执行

A subtle point to notice about RUN is that it's treated as a pure function even if there are side-effects, and is thus cached.关于 RUN 需要注意的一个微妙点是,即使有副作用,它也被视为纯函数,因此被缓存。 What this means is that if RUN had some side effects that don't change the resultant image, and that image has already been cached, the RUN won't be executed again and so the side effects won't happen on subsequent builds.这意味着如果 RUN 有一些不会改变结果图像的副作用,并且该图像已经被缓存,那么 RUN 将不会再次执行,因此在后续构建中不会发生副作用。 For example, take this Dockerfile:例如,以这个 Dockerfile 为例:

FROM busybox
RUN echo "Just echo while you work"

First time you run it, you'll get output such as this, with different alphanumeric IDs:第一次运行它时,你会得到这样的输出,带有不同的字母数字 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

Notice that the echo statement was executed in the above.请注意,echo 语句是在上面执行的。 Second time you run it, it uses the cache, and you won't see any echo in the output of the build:第二次运行它时,它使用缓存,并且您不会在构建的输出中看到任何回声:

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

Note: Don't confuse RUN with CMD.注意:不要将 RUN 与 CMD 混淆。 RUN actually runs a command and commits the result; RUN 实际运行一个命令并提交结果; CMD does not execute anything at build time, but specifies the intended command for the image. CMD 在构建时不执行任何操作,而是指定映像的预期命令。

from docker file reference来自 docker 文件参考

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

RUN Command: RUN command will basically, execute the default command, when we are building the image. RUN 命令:RUN 命令基本上会在我们构建映像时执行默认命令。 It also will commit the image changes for next step.它还将为下一步提交图像更改。

There can be more than 1 RUN command, to aid in process of building a new image.可以有 1 个以上的 RUN 命令,以帮助构建新映像的过程。

CMD Command: CMD commands will just set the default command for the new container. CMD 命令:CMD 命令只会为新容器设置默认命令。 This will not be executed at build time.这不会在构建时执行。

If a docker file has more than 1 CMD commands then all of them are ignored except the last one.如果一个 docker 文件有 1 个以上的 CMD 命令,那么除了最后一个之外,所有这些命令都会被忽略。 As this command will not execute anything but just set the default command.由于此命令不会执行任何操作,只会设置默认命令。

RUN : Can be many, and it is used in build process, eg install multiple libraries RUN : 可以很多,在构建过程中使用,例如安装多个库

CMD : Can only have 1, which is your execute start point (eg ["npm", "start"] , ["node", "app.js"] ) CMD : 只能有 1 个,这是你的执行起点(例如["npm", "start"] , ["node", "app.js"]

There has been enough answers on RUN and CMD .关于RUNCMD已经有足够的答案了。 I just want to add a few words on ENTRYPOINT .我只想在ENTRYPOINT上添加几句话。 CMD arguments can be overwritten by command line arguments, while ENTRYPOINT arguments are always used. CMD参数可以被命令行参数覆盖,而ENTRYPOINT参数总是被使用。

This article is a good source of information.这篇文章是一个很好的信息来源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM