> For the complete documentation index, see [llms.txt](https://yeasy.gitbook.io/docker_practice/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yeasy.gitbook.io/docker_practice/di-er-bu-fen-jin-jie-pian/07_dockerfile/7.15_shell.md).

# 7.15 SHELL 指令

## 7.15.1 基本语法

```docker
SHELL ["executable", "parameters"]
```

`SHELL` 指令允许覆盖 Docker 默认的 shell。

* **Linux 默认**：`["/bin/sh", "-c"]`
* **Windows 默认**：`["cmd", "/S", "/C"]`

该指令会影响后续的 `RUN`，`CMD`，`ENTRYPOINT` 指令 (当它们使用 shell 格式时)。

***

## 7.15.2 为什么要用 SHELL 指令

### 1. 使用 bash 特性

默认的 `/bin/sh` (通常是 dash 或 alpine 的 ash) 功能有限。如果你需要使用 bash 的特有功能 (如数组、`{}` 扩展、`pipefail` 等)，可以切换 shell。

```docker
FROM ubuntu:24.04

## 切换到 bash

SHELL ["/bin/bash", "-c"]

## 现在可以使用 bash 特性了

RUN echo {a..z}
```

### 2. 增强错误处理

默认情况下，管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功，整个指令就视为成功。这可能掩盖构建错误。

```docker
## ❌ 这里的 wget 失败了，但构建继续（因为 tar 成功了）

RUN wget -O - https://invalid-url | tar xz
```

使用 `SHELL` 启用 `pipefail`：

```docker
## ✅ 启用 pipefail

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

## 如果 wget 失败，整个 RUN 就会失败

RUN wget -O - https://invalid-url | tar xz
```

### 3. Windows 环境

在 Windows 容器中，经常需要在 `cmd` 和 `powershell` 之间切换。

```docker
FROM mcr.microsoft.com/windows/servercore:ltsc2022

## 默认是 cmd

RUN echo Default shell is cmd

## 切换到 powershell

SHELL ["powershell", "-command"]
RUN Write-Host "Hello from PowerShell"

## 切回 cmd

SHELL ["cmd", "/S", "/C"]
```

***

## 7.15.3 作用范围

`SHELL` 指令可以出现多次，每次只影响其后的指令：

```docker
FROM ubuntu:24.04

## 使用默认 sh

RUN echo "Using sh"

SHELL ["/bin/bash", "-c"]

## 使用 bash

RUN echo "Using bash"

SHELL ["/bin/sh", "-c"]

## 回到 sh

RUN echo "Using sh again"
```

***

## 7.15.4 对其他指令的影响

`SHELL` 影响的是所有使用 **shell 格式** 的指令：

| 指令格式                           | 是否受 SHELL 影响 |
| ------------------------------ | ------------ |
| `RUN command`                  | ✅ 是          |
| `RUN ["exec", "param"]`        | ❌ 否          |
| `CMD command`                  | ✅ 是          |
| `CMD ["exec", "param"]`        | ❌ 否          |
| `ENTRYPOINT command`           | ✅ 是          |
| `ENTRYPOINT ["exec", "param"]` | ❌ 否          |

***

## 7.15.5 最佳实践

### 1. 推荐开启 pipefail

对于使用 bash 的镜像，强烈建议开启 `pipefail`，以确保构建过程中的错误能被及时捕获。

```docker
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
```

### 2. 明确意图

如果由于脚本需求必须更改 shell，最好在 Dockerfile 中显式声明，而不是依赖默认行为。

### 3. 尽量保持一致

避免在 Dockerfile 中频繁切换 SHELL，这会使构建过程难以理解和调试。尽量在头部定义一次即可。

***


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://yeasy.gitbook.io/docker_practice/di-er-bu-fen-jin-jie-pian/07_dockerfile/7.15_shell.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
