😰 生产环境的紧急电话
上周五晚上,正准备下班,运维打来电话:
"新上的服务,镜像太大,部署要 5 分钟,能不能优化一下?"
我一看镜像大小:2.1 GB 😱
问题来了:
- 镜像太大,拉取慢
- 部署时间长,影响发布
- 磁盘空间占用高
我的目标:
- 镜像大小降到 200MB 以下
- 部署时间降到 30 秒以内
🔍 问题分析
1. 为什么镜像这么大?
检查 Dockerfile:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
vim \
curl \
wget \
&& rm -rf /var/lib/apt/lists/*
COPY . /app
WORKDIR /app
RUN pip3 install -r requirements.txt
CMD ["python3", "app.py"]
问题:
- ✅ 使用
ubuntu基础镜像(太大) - ✅ 安装了不必要的工具(vim, curl, wget)
- ✅ 没有使用
.dockerignore - ✅ 没有多阶段构建
2. 镜像大小分析
# 查看镜像层大小
docker history myapp:latest
# 结果
IMAGE CREATED SIZE
myapp:latest 2 minutes ago 2.1GB
<none> 5 minutes ago 1.8GB # Python 依赖
<none> 8 minutes ago 300MB # 系统工具
<none> 10 minutes ago 72MB # Ubuntu 基础
🛠️ 优化方案
方案 1:使用 Alpine 基础镜像
问题: Ubuntu 基础镜像 72MB,包含很多不必要的组件。
解决: 使用 Alpine 基础镜像(5MB)
FROM python:3.9-alpine
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
效果:
- 之前:2.1 GB
- 现在:850 MB
- 减少:60%
方案 2:多阶段构建
问题: 构建依赖(gcc, make)也被打包进镜像。
解决: 多阶段构建,只保留运行时文件。
# 构建阶段
FROM python:3.9-alpine AS builder
WORKDIR /app
COPY requirements.txt .
RUN 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 . .
CMD ["python", "app.py"]
效果:
- 之前:850 MB
- 现在:180 MB
- 减少:79%
方案 3:优化 .dockerignore
问题: 不必要的文件被打包进镜像(.git, pycache, 测试文件)。
解决: 创建 .dockerignore 文件
.git
.gitignore
__pycache__
*.pyc
*.pyo
*.pyd
.env
.venv
venv/
tests/
*.md
Dockerfile
效果:
- 之前:180 MB
- 现在:165 MB
- 减少:8%
方案 4:清理 pip 缓存
问题: pip 安装包后缓存文件还在。
解决: 使用 --no-cache-dir
RUN pip install --no-cache-dir -r requirements.txt
方案 5:合并 RUN 指令
问题: 每个 RUN 指令创建一个镜像层。
解决: 合并 RUN 指令
# 之前
RUN apk add --no-cache git
RUN apk add --no-cache curl
RUN apk add --no-cache vim
# 之后
RUN apk add --no-cache git curl vim
🎯 最终效果
优化前 vs 优化后
| 指标 | 优化前 | 优化后 | 改善 |
|---|---|---|---|
| 镜像大小 | 2.1 GB | 165 MB | 减少 92% |
| 构建时间 | 8 分钟 | 3 分钟 | 减少 62% |
| 部署时间 | 5 分钟 | 10 秒 | 减少 97% |
| 磁盘占用 | 2.5 GB | 200 MB | 减少 92% |
最终 Dockerfile
FROM python:3.9-alpine
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN addgroup -g 1000 appuser && \
adduser -D -u 1000 -G appuser appuser
USER appuser
CMD ["python", "app.py"]
💡 最佳实践总结
1. 选择合适的基础镜像
# ✅ 推荐
FROM python:3.9-alpine # 5MB
FROM node:16-alpine # 40MB
# ❌ 避免
FROM ubuntu:latest # 72MB
FROM python:3.9 # 900MB
2. 使用多阶段构建
# 构建阶段
FROM golang:1.19 AS builder
WORKDIR /app
COPY . .
RUN go build -o app
# 运行阶段
FROM alpine:latest
COPY --from=builder /app/app /app
CMD ["/app"]
3. 优化镜像层
# ✅ 合并 RUN 指令
RUN apk add --no-cache git curl vim && \
rm -rf /var/cache/apk/*
# ❌ 多个 RUN 指令
RUN apk add --no-cache git
RUN apk add --no-cache curl
RUN apk add --no-cache vim
4. 使用 .dockerignore
.git
.gitignore
__pycache__
*.pyc
*.pyo
.env
.venv
tests/
5. 清理缓存
# Python
RUN pip install --no-cache-dir -r requirements.txt
# Node.js
RUN npm ci --only=production && \
npm cache clean --force
# Go
RUN go mod download && \
go mod verify
⚠️ 常见坑
坑 1:忘记使用 alpine 镜像
问题: 使用标准镜像,体积大 10 倍以上。
解决: 优先使用 alpine 镜像。
坑 2:打包开发依赖
问题: 测试框架、开发工具被打包进镜像。
解决: 多阶段构建,只打包运行时依赖。
坑 3:忽略 .dockerignore
问题: .git, pycache 等文件被打包进镜像。
解决: 创建 .dockerignore 文件。
坑 4:使用 root 用户运行
问题: 安全风险。
解决: 创建专用用户运行应用。
RUN addgroup -g 1000 appuser && \
adduser -D -u 1000 -G appuser appuser
USER appuser
📊 延伸思考
1. 镜像越小越好吗?
不一定。需要权衡:
- 开发环境:可以使用较大的镜像,包含调试工具
- 生产环境:使用最小镜像,减少攻击面
2. 如何监控镜像大小?
# 查看所有镜像大小
docker images
# 查看镜像历史
docker history myapp:latest
# 查看镜像层大小
docker inspect myapp:latest | jq '.[0].RootFS.Layers[]'
3. 自动化检查
在 CI/CD 中添加镜像大小检查:
# .github/workflows/docker.yml
- name: Check image size
run: |
size=$(docker images myapp:latest --format "{{.Size}}")
if [ ${size%MB} -gt 200 ]; then
echo "镜像太大:$size"
exit 1
fi
🎉 总结
通过 5 个优化方案:
- ✅ 使用 Alpine 基础镜像
- ✅ 多阶段构建
- ✅ 优化 .dockerignore
- ✅ 清理 pip 缓存
- ✅ 合并 RUN 指令
最终效果:
- 镜像从 2.1 GB → 165 MB
- 部署时间从 5 分钟 → 10 秒
- 减少 92%
关键经验:
- 优先选择 alpine 基础镜像
- 使用多阶段构建分离构建和运行
- 创建 .dockerignore 排除不必要文件
- 清理缓存,合并镜像层
- 使用非 root 用户运行应用
🎯 下一步:
- 尝试使用 distroless 镜像(Google 出品,更小更安全)
- 研究镜像扫描工具(Trivy, Clair)
- 优化 CI/CD 流程,自动化镜像检查
💬 你的 Docker 镜像多大?有什么优化经验?欢迎评论区分享!