web学习笔记编程技术学习与分享

Docker 镜像分层与构建缓存

2026 年 08 月 12 日约 3 分钟阅读 运维与部署

镜像不是一个大压缩包,而是由一系列只读层堆叠而成。每条 Dockerfile 指令生成一层,理解分层是优化构建的前提。

分层与缓存

构建时 Docker 逐条比对指令:指令没变、上下文相关文件没变,直接复用缓存层。一旦某层失效,其后的所有层全部重建。

# 反例:代码一改,依赖全重装
COPY . /app
RUN pip install -r requirements.txt

# 正例:依赖文件不变时,安装层永远命中缓存
COPY requirements.txt /app/
RUN pip install -r /app/requirements.txt
COPY . /app

这条「把变动少的放前面」是 Dockerfile 优化的核心。

镜像为什么大

常见原因按频率排序:

  1. 包管理器缓存:apt-get update 和 install 没合并成一层,或没清理列表;
  2. 调试工具:curl、vim、git 进了生产镜像;
  3. COPY . . 把 .git、node_modules、日志全拷进去——用 .dockerignore 排除;
  4. 多阶段构建没用上:编译工具链(gcc、node 全量)留在了最终镜像。
# 多阶段:构建环境不进入运行镜像
FROM node:22 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html

层是只读的

运行时的写操作发生在可写层,容器删除即消失。不要把持久化数据写在容器内——数据库文件、上传文件用 volume 挂载。同理,镜像内用 RUN echo > /etc/app.conf 再被 volume 覆盖是常见误操作。

标签与清理

latest 标签会漂移,回滚时找不到确切版本。CI 里同时打两个标签:语义版本 + git sha。定期清理构建垃圾:

docker image prune -f
docker builder prune -f   # BuildKit 缓存也会占空间

一条检验标准

docker history <image> 能看到每层的大小和指令。从上往下找最大的几层问自己:这一层在生产运行时需要吗?不需要,就是优化空间。镜像从 1.2GB 降到 200MB 通常只需要一轮这样的审视。

Docker镜像CI/CD