Files
docker_practice/image/dockerfile/shell.md
2026-01-30 16:48:39 -08:00

3.2 KiB
Raw Blame History

SHELL 指令

基本语法

SHELL ["executable", "parameters"]

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

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

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


为什么要用 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. 增强错误处理 (pipefail)

默认情况下,管道命令 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 容器中,经常需要在 cmdpowershell 之间切换。

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"]

作用范围

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"

对其他指令的影响

SHELL 影响的是所有使用 shell 格式 的指令:

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

最佳实践

1. 推荐开启 pipefail

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

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

2. 明确意图

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

3. 尽量保持一致

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


本章小结

要点 说明
作用 更改 RUN/CMD/ENTRYPOINT 的默认 shell
Linux 默认 ["/bin/sh", "-c"]
Windows 默认 ["cmd", "/S", "/C"]
推荐用法 SHELL ["/bin/bash", "-o", "pipefail", "-c"]
影响范围 后续所有使用 shell 格式的指令

延伸阅读