合理安排 Dockerfile 指令顺序以最大化缓存复用:变化少的指令靠前,如固定标签的基础镜像、合并的系统依赖安装;依赖文件先于源码复制;用 COPY 替代 ADD;多阶段构建分离编译与运行环境。

合理安排 Dockerfile 指令顺序,核心是让构建缓存尽可能复用——变化少的指令靠前,变化频繁的靠后。Docker 每条指令生成一层,一旦某层失效(哈希值不同),它及之后所有层都会重新构建。
基础镜像与系统依赖必须放最前面
FROM 和系统级安装(如 apt-get、apk add)几乎不随业务迭代变动,应紧贴开头。用固定标签替代 latest,例如 FROM ubuntu:22.04 而非 FROM ubuntu:latest,避免上游镜像更新导致整条缓存链断裂。
- 合并 apt 更新、安装、清理为单条 RUN: RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
- 避免在 RUN 中调用带时间戳、随机数或网络请求的命令(如 date、curl https://api.example.com/time),它们每次生成不同哈希,强制缓存失效
应用依赖和源码分开放置
依赖文件(如 package.json、requirements.txt、pom.xml)比源码更稳定。先 COPY 依赖清单,再 RUN 安装,最后 COPY 源码。这样只要代码改动,不会触发依赖重装。
- Node.js 示例:COPY package*.json ./ → RUN npm ci --only=production → COPY . .
- Python 示例:COPY requirements.txt . → RUN pip install --no-cache-dir -r requirements.txt → COPY . .
减少中间层残留和权限干扰
每层都保留上层的所有文件,冗余内容会膨胀镜像体积并影响缓存命中率。
- 用 COPY 替代 ADD,除非需要自动解压 tar 包;ADD 有隐式行为,容易引入不可控变化
- 敏感操作(如创建用户、设置权限)尽量合并到同一 RUN 中,避免多层留下临时状态
- 使用 WORKDIR 明确路径,避免隐式路径叠加导致 COPY 行为不可预期
多阶段构建适合生产镜像瘦身
编译环境和运行环境分离,可大幅减小最终镜像体积,同时天然规避开发期文件污染运行层。
- 第一阶段用 golang:1.22 构建二进制,第二阶段用 alpine:3.20 仅 COPY 可执行文件
- 构建阶段的依赖、源码、缓存全部不进入最终镜像,不影响运行层缓存逻辑


















