# 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指令**的缓存无效。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://camelgemonion.gitbook.io/docker/dockerfile-zhi-ling/run.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
