镜像优化策略

减小镜像体积、提升构建速度的优化策略


📋 目录


选择合适的基础镜像

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~170MBNode.js + Alpine
node:16~900MBNode.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

优势

  1. 减小镜像体积:只保留运行时需要的文件
  2. 提高安全性:不包含构建工具和源代码
  3. 优化构建缓存:构建阶段和运行阶段分离

多阶段构建示例

# 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:latest

docker images

查看镜像总大小。

# 查看所有镜像大小
docker images
 
# 按大小排序
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | sort -k3 -h

dive

第三方工具,可视化分析镜像层。

# 安装 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:latest

docker 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:latest

2. 最小化文件复制

# 只复制必要的文件
COPY package.json package-lock.json ./
COPY src/ ./src/
# 而不是 COPY . .

3. 使用 .dockerignore

排除不必要的文件,减小构建上下文。

node_modules/
.git/
*.md
test/
.env

4. 压缩文件系统

# 使用压缩工具
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
  • 只复制必要的文件
  • 分析镜像大小,找出占用大的层

📚 参考资源


相关笔记