镜像优化策略
减小镜像体积、提升构建速度的优化策略
📋 目录
选择合适的基础镜像
Alpine vs 标准镜像
Alpine Linux 是一个基于 musl libc 和 BusyBox 的轻量级 Linux 发行版。
# 使用 Alpine(体积小,约 5MB)
FROM alpine:latest
# 使用标准镜像(体积大,约 100MB+)
FROM ubuntu:20.04镜像大小对比
| 基础镜像 | 大小 | 特点 |
|---|---|---|
| alpine:latest | ~5MB | 最小,但兼容性可能有问题 |
| debian:bullseye-slim | ~80MB | 平衡体积和兼容性 |
| ubuntu:20.04 | ~72MB | 兼容性好,体积较大 |
| node:16-alpine | ~170MB | Node.js + Alpine |
| node:16 | ~900MB | Node.js 标准镜像 |
选择建议
- 生产环境:优先使用 Alpine 或 slim 版本
- 开发环境:可以使用标准镜像,工具更全
- 兼容性要求高:使用标准镜像
减少镜像层数
层数限制
Docker 镜像最多支持 127 层,但实际建议控制在 10-20 层以内。
优化方法
# 不好的做法:多个指令创建多个层
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
# 好的做法:合并指令减少层数
RUN apt-get update && \
apt-get install -y nginx curl && \
rm -rf /var/lib/apt/lists/*合并 RUN 指令
原则
将相关的操作合并到一个 RUN 指令中,减少镜像层数。
# 不好的做法
RUN apt-get update
RUN apt-get install -y python3
RUN apt-get install -y pip
RUN pip install flask
# 好的做法
RUN apt-get update && \
apt-get install -y python3 pip && \
pip install flask && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*注意事项
- 使用
&&连接命令,确保前一个命令成功才执行下一个 - 使用
\进行换行,提高可读性 - 在最后清理缓存和临时文件
清理不必要的文件
清理包管理器缓存
# Debian/Ubuntu
RUN apt-get update && \
apt-get install -y nginx && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# CentOS/RHEL
RUN yum install -y nginx && \
yum clean all && \
rm -rf /var/cache/yum
# Alpine
RUN apk add --no-cache nginx && \
rm -rf /var/cache/apk/*清理构建依赖
# 多阶段构建中,只保留运行时需要的文件
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
# 只复制构建产物,不复制 node_modules
COPY --from=builder /app/dist /usr/share/nginx/html删除临时文件
RUN wget https://example.com/file.tar.gz && \
tar -xzf file.tar.gz && \
rm file.tar.gz # 删除下载的压缩包使用多阶段构建
基本语法
# 构建阶段
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 运行阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html优势
- 减小镜像体积:只保留运行时需要的文件
- 提高安全性:不包含构建工具和源代码
- 优化构建缓存:构建阶段和运行阶段分离
多阶段构建示例
# Go 应用多阶段构建
FROM golang:1.18 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/app .
CMD ["./app"]镜像大小分析工具
docker history
查看镜像各层大小。
# 查看镜像构建历史
docker history nginx:latest
# 人类可读格式
docker history --human nginx:latest
# 不截断输出
docker history --no-trunc nginx:latestdocker images
查看镜像总大小。
# 查看所有镜像大小
docker images
# 按大小排序
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | sort -k3 -hdive
第三方工具,可视化分析镜像层。
# 安装 dive
brew install dive # macOS
# 或
wget https://github.com/wagoodman/dive/releases/download/v0.10.0/dive_0.10.0_linux_amd64.tar.gz
# 使用 dive 分析镜像
dive nginx:latestdocker system df
查看 Docker 系统占用空间。
# 查看空间使用情况
docker system df
# 详细查看
docker system df -v优化实践案例
Node.js 应用优化
优化前
FROM node:16
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]问题:
- 包含 node_modules(体积大)
- 包含源代码
- 包含构建工具
优化后
# 构建阶段
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 运行阶段
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
CMD ["node", "dist/index.js"]优化效果:
- 使用 Alpine 基础镜像
- 分离构建和运行环境
- 只保留运行时需要的文件
Python 应用优化
优化前
FROM python:3.9
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]优化后
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]优化点:
- 使用 slim 版本
- 使用
--no-cache-dir不缓存 pip 包 - 先复制 requirements.txt,利用缓存
其他优化技巧
1. 使用特定标签
# 好的做法:使用具体版本
FROM node:16.14.2-alpine
# 不好的做法:使用 latest
FROM node:latest2. 最小化文件复制
# 只复制必要的文件
COPY package.json package-lock.json ./
COPY src/ ./src/
# 而不是 COPY . .3. 使用 .dockerignore
排除不必要的文件,减小构建上下文。
node_modules/
.git/
*.md
test/
.env4. 压缩文件系统
# 使用压缩工具
RUN tar -czf /tmp/data.tar.gz /data && \
rm -rf /data && \
mkdir /data && \
tar -xzf /tmp/data.tar.gz -C /data && \
rm /tmp/data.tar.gz优化检查清单
- 使用 Alpine 或 slim 基础镜像
- 合并 RUN 指令减少层数
- 清理包管理器缓存
- 使用多阶段构建
- 删除临时文件和构建依赖
- 使用 .dockerignore 排除不必要文件
- 使用特定版本标签而非 latest
- 只复制必要的文件
- 分析镜像大小,找出占用大的层