CI 缓存构建层
为什么 Docker 构建缓存如此重要
每次 CI 构建都完整执行 Dockerfile 会导致:
– 构建时间长(尤其是有编译步骤的应用)
– 网络带宽浪费(重复下载依赖)
– CI 队列积压
利用 Docker 的层缓存机制可以大幅提速。
Docker 构建缓存原理
Docker 构建的每一层都是缓存单元。当某层指令和上下文未变化时,Docker 直接复用缓存层。
# 依赖层——变化频率低,应放在前面
FROM node:18 AS builder
WORKDIR /app
COPY package.json package-lock.json ./ # 只复制依赖文件
RUN npm ci --only=production # 安装依赖(可缓存)
COPY . . # 复制源码(变化频繁)
RUN npm run build
如果 package.json 没变,则 npm ci 层复用缓存,直接跳到 COPY . . 之后。
CI 中的缓存策略
策略一:–cache-from
# 从远程仓库拉取缓存
docker pull registry.example.com/myapp:latest || true
# 使用拉取的镜像作为缓存来源
docker build \
--cache-from registry.example.com/myapp:latest \
-t registry.example.com/myapp:${BUILD_TAG} .
策略二:BuildKit 缓存挂载
# syntax=docker/dockerfile:1
FROM golang:1.21 AS builder
WORKDIR /app
RUN --mount=type=cache,target=/root/.cache/go-build \
go build -o /app/server .
FROM node:18
WORKDIR /app
RUN --mount=type=cache,target=/root/.npm \
npm ci
策略三:共享缓存卷
# docker-compose CI 配置
services:
builder:
image: node:18
volumes:
- npm-cache:/root/.npm
- .:/app
working_dir: /app
command: npm ci && npm run build
volumes:
npm-cache:
不同语言的最佳缓存实践
| 语言 | 缓存目录 | 策略 |
|---|---|---|
| Node.js | /root/.npm、node_modules/.cache |
先 copy package.json,安装后再 copy 源码 |
| Go | /root/.cache/go-build |
使用 --mount=type=cache |
| Java/Maven | /root/.m2 |
挂载 Maven 本地仓库 |
| Python | /root/.cache/pip |
使用 pip cache |
| Rust | /root/.cargo、target |
使用 sccache 或 cargo chef |
多阶段构建 + 缓存
# Stage 1: 依赖安装(低频变化)
FROM node:18 AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# Stage 2: 构建(高频变化)
FROM node:18 AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Stage 3: 运行(最小镜像)
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
面试要点
- Docker 构建缓存基于指令哈希和上下文校验
- 将低频变化的指令放在 Dockerfile 前面
- BuildKit 的
--mount=type=cache是高级缓存手段 - CI 中合理利用缓存可减少 50%-90% 的构建时间
--cache-from让远程构建也能享受缓存
面试官常问:你们在 CI 中用了哪些缓存技巧?构建时间优化了多少?
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容