Files
docker_practice/07_dockerfile/7.15_shell.md
T
yeasy ef2625531d style: 含中文的括号统一为全角(336 处 / 110 文件)
全书此前是真·五五开:含中文的括号 336 处半角 : 336 处全角,而且**在同一文件
内混用**——`18_security/18.1_kernel_ns.md` 第 11/17/20 行写 `(如 runC)`,
第 31 行写 `(用户命名空间映射)`。这不是体例问题,是它自己跟自己不一致。

集群里其余 13 本都一边倒(llm_internals 5 : 1049、oc_guide 2 : 713、
forward_deployed_engineering_guide 0 : 108),blockchain_guide 已在 2026-08-05
按同一方向统一过 97 处,故取全角,而非另立新规。全角括号前后不留空格,
原先 `概念 (镜像、容器、仓库) 和` 两侧的空格一并收掉。

**纯拉丁内容的半角括号一个没动**——`新建一个层 (Layer)`、`项目 (project)`
保持原样:改动前后「半角且内容纯拉丁」的数量都是 **1163**,而「半角且含中文」
从 **336 变成 0**。

其余验证:改动前后各自抹掉全部空白与圆括号后**逐字节相同**(两侧均 19559 字符);
左右括号总数改动前后都是 399 : 399,证明没有吞括号也没有配错对。
`check_project_rules` 202/202、`check_emphasis` 202/202、37 tests OK、
根 `format_checker` 与 `validate_codeblocks` 干净、`git diff --check` 干净。
2026-08-24 13:13:23 -07:00

2.8 KiB
Raw Blame History

7.15 SHELL 指令

7.15.1 基本语法

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。

FROM ubuntu:24.04

## 切换到 bash

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

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

RUN echo {a..z}

2. 增强错误处理

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

## ❌ 这里的 wget 失败了,但构建继续(因为 tar 成功了)

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

使用 SHELL 启用 pipefail:

## ✅ 启用 pipefail

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

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

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

3. Windows 环境

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

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 指令可以出现多次,每次只影响其后的指令:

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,以确保构建过程中的错误能被及时捕获。

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

2. 明确意图

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

3. 尽量保持一致

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