mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-02-27 12:39:28 +00:00
3.8 KiB
3.8 KiB
RUN 执行命令
基本语法
RUN <command>
RUN ["executable", "param1", "param2"]
RUN 指令是 Dockerfile 中最常用的指令之一。它在当前镜像层之上创建一个新层,执行指定的命令,并提交结果。
两种格式对比
1. Shell 格式
RUN apt-get update
- 特点:默认通过
/bin/sh -c执行。 - 优势:可以使用环境变量、管道、重定向等 Shell 特性。
- 示例:
RUN echo "Hello" > /test.txt
2. Exec 格式
RUN ["apt-get", "update"]
- 特点:直接调用可执行文件,不经过 Shell。
- 优势:避免 Shell 字符串解析问题,适用于参数中包含特殊字符的情况。
- 注意:无法使用
$VAR环境变量替换(除非显式调用 shell)。
常见最佳实践
1. 组合命令(减少层数)
每一个 RUN 指令都会新建一层镜像。为了减少镜像体积和层数,应使用 && 连接命令。
❌ 糟糕的写法(创建 3 层):
RUN apt-get update
RUN apt-get install -y nginx
RUN rm -rf /var/lib/apt/lists/*
✅ 推荐写法(创建 1 层):
RUN apt-get update && \
apt-get install -y nginx && \
rm -rf /var/lib/apt/lists/*
2. 清理缓存
在安装完软件后,立即清除缓存,可以显著减小镜像体积。
- Debian/Ubuntu:
RUN apt-get update && apt-get install -y package-bar \ && rm -rf /var/lib/apt/lists/* - Alpine:
RUN apk add --no-cache package-bar
3. 使用 set -e 和 pipefail
默认情况下,管道命令 cmd1 | cmd2 只要 cmd2 成功,整个 RUN 就视为成功。
❌ 隐蔽的错误:
# 如果下载失败,gzip 可能会报错,但如果不影响后续,构建可能继续
RUN wget http://error-url | gzip -d > file
✅ 推荐写法:
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN wget http://url | gzip -d > file
常见问题
Q: 为什么 RUN cd /app 不生效?
RUN cd /app
RUN touch hello.txt
结果:hello.txt 会出现在根目录 /,而不是 /app。
原因:每个 RUN 都在一个新的 Shell/容器 环境中执行。cd 只影响当前 RUN 的环境。
解决:使用 WORKDIR 指令。
WORKDIR /app
RUN touch hello.txt
Q: 环境变量不生效?
RUN export MY_VAR=hello
RUN echo $MY_VAR
结果:输出为空。
原因:同上,环境变量只在当前 RUN 有效。
解决:使用 ENV 指令,或在同一行 RUN 中导出。
ENV MY_VAR=hello
RUN echo $MY_VAR
高级技巧
1. 使用 BuildKit 的挂载缓存
BuildKit 支持在 RUN 指令中使用 --mount 挂载缓存,加速构建。
# 缓存 apt 包
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install -y gcc
# 缓存 Go 模块
RUN --mount=type=cache,target=/go/pkg/mod \
go build -o app
2. 挂载密钥
安全地使用 SSH 密钥或 Token,而不将其记录在镜像中。
RUN --mount=type=secret,id=mysecret \
cat /run/secrets/mysecret
本章小结
| 要点 | 说明 |
|---|---|
| 作用 | 在新层执行命令 |
| 原则 | 合并命令,清理缓存 |
| 格式 | Shell (常用) vs Exec |
| 陷阱 | cd 不持久,环境变量不持久 |
| 进阶 | 使用 Cache Mount 加速构建 |
延伸阅读
- CMD 容器启动命令:容器启动时的命令
- WORKDIR 指定工作目录:改变目录
- Dockerfile 最佳实践