多阶段构建是Docker官方推荐的减小镜像体积的核心手段,通过多个FROM划分构建与运行阶段,仅复制必要产物到精简基础镜像,并配合.dockerignore、小基础镜像、缓存清理和非root用户等优化措施。

多阶段构建是 Docker 官方推荐的减小镜像体积的核心手段,它通过在同一个 Dockerfile 中使用多个 FROM 指令定义不同构建阶段,只将最终运行所需的文件复制到精简的运行时镜像中,从而剥离编译工具、源码、依赖缓存等非必要内容。
明确划分构建阶段与运行阶段
典型做法是用一个含完整编译环境的镜像(如 golang:1.22-alpine 或 node:20-slim)作为构建阶段,完成代码编译、依赖安装、打包;再用一个极小的基础镜像(如 alpine:latest 或 debian:slim)作为运行阶段,仅拷贝构建产物。
- 构建阶段用
AS <name>命名,便于后续引用,例如:FROM golang:1.22-alpine AS builder - 运行阶段不加
AS,或显式命名为runner,保持语义清晰 - 避免在运行阶段重复安装构建工具或开发依赖(如
gcc、python3-dev)
精准复制构建产物,不带冗余文件
使用 COPY --from=<stage_name> 只拷贝真正需要的二进制、配置、静态资源,跳过 /src、/go、node_modules(除非运行时真要动态 require)、测试文件、文档等。
- Go 示例:
COPY --from=builder /app/myserver /usr/local/bin/myserver - Node.js 示例:先在 builder 阶段
npm ci --only=production,再COPY --from=builder /app/node_modules /app/node_modules和COPY --from=builder /app/dist /app/dist - 可配合
.dockerignore过滤本地不需要送入构建上下文的文件(如node_modules/、.git/、tests/)
选用更小的基础镜像并精简运行时依赖
运行阶段优先选 alpine(约 5MB)或 debian:slim(约 80MB),而非 ubuntu(约 200MB+)或默认 tag(常为 full 版本)。
- Alpine 注意:某些 C 扩展(如 Python 的
cryptography)需适配 musl libc,必要时改用debian:slim并手动删包(如apt-get purge -y --auto-remove) - 使用
apk del(Alpine)或apt-get clean+rm -rf /var/lib/apt/lists/*(Debian)清理包管理缓存 - 用
USER nonroot:nonroot切换非 root 用户,既提升安全,也避免因权限问题导致的隐式体积膨胀(如残留的 root-owned 缓存目录)
验证与对比优化效果
构建后用 docker images 查看大小变化,再用 docker history <image> 分析各层体积分布,确认大层是否已被消除。
- 若某层仍很大(如 “RUN npm install” 占 300MB),说明未正确分离构建与运行阶段,或未启用 production 模式
- 可用
docker run --rm -it <image> sh -c 'du -sh /* 2>/dev/null | sort -hr | head -10'快速定位镜像内大目录 - 结合
docker build --progress=plain观察每步实际写入大小,排查意外缓存或复制

















