> For the complete documentation index, see [llms.txt](https://camelgemonion.gitbook.io/docker/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://camelgemonion.gitbook.io/docker/dockerfile-zhi-ling/run.md).

# RUN

**RUN有2种形式：**

* **RUN （shell形式，该命令在shell中运行，在Linux上默认为/bin/sh -c，在Windows上默认为cmd /S/C）**
* **RUN \["executable",  "param1",  "param2"]（exec 形式）**

**RUN指令**在当前镜像顶部的新&#x5C42;**（new layer）**&#x4E2D;执行任何命令，并提交结果。生成的提交&#x7684;**（committed）**&#x955C;像将用于**Dockerfile**构建过程中的下一步。

分层运行**RUN指令**并生成**提交（committed）**&#x7B26;合**Docker**的核心概念，在**Docker**中，**提交（committed）**&#x5F88;廉价，并且可以从镜像历史记录的任何位置创建容器，特别像源代码控制。

**exec**形式可以避免破坏**shell**字符串，并使用不包含指定**shell executable**的基本镜像运行**RUN命令**。

可以使用**SHELL命令**更改**shell**形式的默认**shell**。

在**shell**形式中，可以使&#x7528;**\（反斜杠）**&#x5C06;一条**RUN指令**继续到下一行。例如，考虑以下两行：

```
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
```

它们在一起等价于以下这一行：

```
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
```

要使&#x7528;**/bin/sh**以外的其他**shell**，请使用**exec**形式传入所需的**shell**。例如：

```
RUN ["/bin/bash", "-c", "echo hello"]
```

**NOTE:**

**exec**形式的指令被解析为**JSON数组**，这意味着对于单词，我们必须使用**双引号**包围，而不是**单引号**。

与**shell**形式不同，**exec**形式不会调用命令行**shell**。这意味着正常的**shell**处理不会发生。例如，**RUN \["echo"，"$HOME"]**&#x4E0D;会&#x5BF9;**$HOME**进行变量替换。如果要进行**shell**处理，可以使用**shell**形式或直接执行**shell**，例如：**RUN \["sh"，"-c"，"echo $HOME"]**。当使用**exec**形式并直接执行**shell**时（例如在**shell**形式中），是由**shell**进行环境变量扩展，而不是**docker**。

**Dockerfile：**

```
# Dockerfile
ARG NAME="TonyYang"

FROM centos:7

ARG NAME

RUN /bin/echo Hello $NAME.

RUN ["echo", "Hello $NAME."]

RUN ["/bin/sh", "-c", "echo Hello $NAME."]
```

**示例一：shell形式**

```
Step 4/6 : RUN /bin/echo Hello $NAME.
 ---> Running in 3bca82f1ce9c
Hello TonyYang. # 执行了变量替换
```

**示例二: exec形式**

```
Step 5/6 : RUN ["echo", "Hello $NAME."]
 ---> Running in 956d8accc7b7
Hello $NAME. # 未执行变量替换
```

**示例三：直接执行shell**

```
Step 6/6 : RUN ["/bin/sh", "-c", "echo Hello $NAME."]
 ---> Running in 5839161cf465
Hello TonyYang. # 执行了变量替换
```

上面我直接将三种形式放在了一个**Dockerfile**中，便于比较。

**NOTE:**

在**JSON**形式中，必须转义反斜杠。这在**Windows**中特别有用，在**Windows**中反斜杠是路径分隔符。由于无效的**JSON**，以下几行将被视为**shell**形式，并以意外的方式执行失败：

```
RUN ["c:\windows\system32\tasklist.exe"]
```

正确的语法示例：

```
RUN ["c:\\windows\\system32\\tasklist.exe"]
```

在下一次构建中，**RUN指令**的缓存不会自动失效。诸如**RUN apt-get dist-upgrade -y**之类的指令的缓存将在下一次构建中重用。可以使&#x7528;**--no-cache**使**RUN指令**的缓存无效，例如**docker build --no-cache**。

可以通过**ADD**和**COPY指令**使**RUN指令**的缓存无效。
