合并run指令是压缩镜像体积与提升构建效率的核心手段:用&&串联安装与清理命令(如apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*),确保操作在同一层完成,避免缓存残留和无效分层。

RUN 指令是 Docker 构建过程中最影响性能的关键环节之一,调得好能大幅缩短构建时间、减小镜像体积、提升缓存命中率;调得随意,很容易让 CI/CD 卡在“等构建”上。
合并多个 RUN 为单条指令
每个 RUN 都会生成一层镜像,层数越多,镜像越大,构建和传输开销越高。更重要的是,Docker 缓存是以每层为单位的——哪怕只改一行命令,后续所有 RUN 都会失效重跑。
- ❌ 不推荐:分散安装依赖
RUN apt-get update && apt-get install -y curl
RUN apt-get install -y git
RUN rm -rf /var/lib/apt/lists/*
- ✅ 推荐:合并 + 清理一步到位
RUN apt-get update && apt-get install -y curl git && rm -rf /var/lib/apt/lists/*
同理,Python 项目中应把 pip 安装和缓存清理写在同一 RUN 中:
RUN pip install --no-cache-dir -r requirements.txt && rm -rf /root/.cache/pip
按变更频率排序 COPY 和 RUN 的顺序
Docker 缓存从上到下逐层比对,一旦某层失效,其后所有层全部重建。源码频繁改动,但依赖文件(如 requirements.txt 或 package.json)相对稳定——那就该让依赖安装尽可能复用缓存。
- ❌ 错误顺序(每次改代码都重装依赖):
COPY . .
RUN pip install -r requirements.txt
- ✅ 正确顺序(仅当依赖文件变化时才重装):
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
Node.js 项目同理:先 COPY package*.json,再 RUN npm install,最后 COPY 其余代码。
避免在 RUN 中执行无意义操作
有些操作看似“干净”,实则破坏缓存或引入冗余:
- 不要在 RUN 中反复执行
apt update(除非你明确需要最新包索引,且已处理好缓存失效问题) - 避免使用
pip install而不加--no-cache-dir,否则 pip 缓存会保留在镜像里,徒增体积 - 不要在中间层留下临时文件(如
git clone后没删掉 .git 目录),建议用--no-cache参数或显式rm -rf
例如 Alpine 环境下编译 Python 包时,装 gcc 又删掉,应写成单条 RUN:
RUN apk add --no-cache gcc musl-dev && pip install -r requirements.txt && apk del gcc musl-dev
配合 .dockerignore 提前过滤干扰项
RUN 指令本身不读取 .dockerignore,但它会影响 COPY 的内容——而 COPY 是 RUN 前最常见的前置操作。如果 .dockerignore 没配好,大量无关文件(如 .git、node_modules、__pycache__)被打包进构建上下文,不仅拖慢 COPY,还会导致缓存更容易失效(比如 Git 提交哈希变动会改变上下文哈希)。
一个实用的 .dockerignore 示例:
.git
__pycache__
*.pyc
.env
node_modules
.dockerignore
这样 COPY . . 实际传入的内容更小、更稳定,RUN 的执行环境也就更可预测。











