<返回目录 Powered by claude/xia兄
第10课: 镜像优化
为什么要优化镜像?
- 减小镜像体积,加快拉取和部署速度
- 降低存储成本
- 减少攻击面,提高安全性
- 提升构建速度
使用轻量级基础镜像
# 对比不同基础镜像大小
FROM ubuntu:20.04 # ~72MB
FROM debian:11-slim # ~80MB
FROM python:3.9 # ~915MB
FROM python:3.9-slim # ~125MB
FROM python:3.9-alpine # ~47MB
FROM alpine:3.18 # ~7MB
# 推荐使用alpine或slim版本
FROM python:3.9-alpine
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
Alpine注意事项:
- 使用musl libc而不是glibc,某些包可能不兼容
- 需要安装编译工具:apk add --no-cache gcc musl-dev
- 包管理器是apk而不是apt
多阶段构建
# 优化前:包含编译工具和源代码(1.2GB)
FROM node:16
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD ["npm", "start"]
# 优化后:只包含运行时文件(150MB)
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
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 package*.json ./
CMD ["npm", "start"]
Go应用极致优化
# 从1GB优化到10MB
FROM golang:1.19 AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags="-w -s" -o main .
FROM scratch
COPY --from=builder /app/main /main
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 8080
ENTRYPOINT ["/main"]
合并RUN指令
# 优化前:每个RUN创建一层
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get install -y curl
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/*
# 优化后:合并为一层
FROM ubuntu:20.04
RUN apt-get update && \
apt-get install -y nginx curl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
清理缓存和临时文件
# Python
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt && \
rm -rf ~/.cache/pip
# Node.js
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && \
npm cache clean --force
# Alpine Linux
FROM alpine:3.18
RUN apk add --no-cache nginx && \
rm -rf /var/cache/apk/*
# Ubuntu/Debian
FROM ubuntu:20.04
RUN apt-get update && \
apt-get install -y nginx && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
优化层缓存
# 优化前:代码变化导致依赖重新安装
FROM python:3.9-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
# 优化后:依赖文件不变时使用缓存
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
使用.dockerignore
# .dockerignore
# 版本控制
.git
.gitignore
.svn
# 依赖目录
node_modules
venv
__pycache__
*.pyc
# 构建产物
dist
build
*.egg-info
# 日志和临时文件
*.log
*.tmp
*.swp
.DS_Store
# 文档和测试
README.md
docs/
tests/
*.test.js
# IDE配置
.vscode
.idea
*.iml
# 环境变量
.env
.env.local
减少镜像层数
# 使用COPY合并多个文件
COPY package.json package-lock.json ./
# 使用通配符
COPY *.conf /etc/nginx/
# 一次性复制整个目录
COPY src/ /app/src/
使用构建参数优化
FROM python:3.9-slim
ARG DEBIAN_FRONTEND=noninteractive
ARG PIP_NO_CACHE_DIR=1
ARG PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
压缩和优化文件
# 压缩静态资源
FROM node:16 AS builder
WORKDIR /app
COPY . .
RUN npm run build && \
find dist -type f -name "*.js" -exec gzip -k {} \; && \
find dist -type f -name "*.css" -exec gzip -k {} \;
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
分析镜像大小
# 查看镜像层大小
docker history myapp:latest
# 查看详细信息
docker history --no-trunc myapp:latest
# 使用dive工具分析镜像
docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
wagoodman/dive:latest myapp:latest
# 导出镜像并查看内容
docker save myapp:latest -o myapp.tar
tar -xf myapp.tar
ls -lh
实战对比
# 优化前的Python应用(915MB)
FROM python:3.9
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
# 优化后的Python应用(50MB)
FROM python:3.9-alpine AS builder
WORKDIR /app
COPY requirements.txt .
RUN apk add --no-cache gcc musl-dev && \
pip install --no-cache-dir -r requirements.txt
FROM python:3.9-alpine
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages
COPY app.py .
CMD ["python", "app.py"]
使用distroless镜像
# Google的distroless镜像(只包含运行时)
FROM golang:1.19 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o main .
FROM gcr.io/distroless/static-debian11
COPY --from=builder /app/main /
EXPOSE 8080
ENTRYPOINT ["/main"]
优化检查清单
- 使用alpine或slim基础镜像
- 使用多阶段构建分离编译和运行环境
- 合并RUN指令减少层数
- 清理包管理器缓存
- 使用.dockerignore排除不必要文件
- 优化COPY指令顺序利用缓存
- 删除临时文件和编译工具
- 使用--no-cache-dir安装依赖
- 压缩静态资源
- 使用dive工具分析镜像
最佳实践
- 优先选择官方镜像的alpine或slim版本
- 生产环境使用多阶段构建
- 定期审查和清理未使用的镜像
- 使用镜像扫描工具检查漏洞
- 为不同环境构建不同大小的镜像
实践练习
- 对比ubuntu和alpine基础镜像的大小差异
- 使用多阶段构建优化一个Node.js应用
- 使用dive工具分析镜像各层大小
- 编写.dockerignore排除不必要的文件
- 将一个1GB的镜像优化到100MB以下