13-Docker进阶-镜像优化与最佳实践
Docker进阶技巧
前面我们已经学习了Docker的基础知识和实战项目,今天我们深入探讨镜像优化、安全加固、性能调优等高级话题。
1. 镜像体积优化
多阶段构建
问题:传统构建方式镜像体积大(包含构建工具)
# 不好:镜像包含gcc、make等构建工具
FROM python:3.11
RUN apt-get update && apt-get install -y gcc
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
# 镜像大小:900MB
解决方案:多阶段构建
# 好:分离构建和运行环境
FROM python:3.11-slim AS builder
RUN apt-get update && apt-get install -y gcc
COPY requirements.txt .
RUN pip install --user -r requirements.txt
FROM python:3.11-slim
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
# 镜像大小:150MB
使用alpine基础镜像
对比:
python:3.11:900MB(完整版)python:3.11-slim:120MB(瘦身版)python:3.11-alpine:50MB(Alpine版)
# 使用alpine
FROM python:3.11-alpine
# 注意:alpine使用musl libc,某些C扩展可能不兼容
# 如果遇到兼容性问题,用slim版本
合并RUN指令
不好:
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y wget
RUN apt-get clean
# 创建4层,每层都有缓存
好:
RUN apt-get update && \
apt-get install -y curl wget && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 只创建1层
清理缓存
# Python:使用--no-cache-dir
RUN pip install --no-cache-dir -r requirements.txt
# apt:清理apt缓存
RUN apt-get update && \
apt-get install -y curl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# npm:清理npm缓存
RUN npm install && npm cache clean --force
利用构建缓存
原理:如果Dockerfile指令和文件没变化,Docker复用缓存。
优化Dockerfile顺序:
# 不常变化的放前面(能复用缓存)
FROM python:3.11-slim
WORKDIR /app
# 依赖文件很少变化
COPY requirements.txt .
RUN pip install -r requirements.txt
# 源代码经常变化
COPY . .
使用.dockerignore
# .dockerignore
.git
.gitignore
__pycache__
*.pyc
*.pyo
venv
.venv
.env
tests/
docs/
*.md
效果:减少构建上下文大小,提高构建速度。
2. 安全加固
不以root用户运行
不好:
FROM python:3.11
# 默认以root运行
好:
FROM python:3.11-slim
# 创建非root用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
# 切换用户
USER appuser
# 运行应用
CMD ["python", "app.py"]
使用特定版本标签
不好:
FROM python:latest
# latest标签可能随时变化
好:
FROM python:3.11.7
# 明确版本,避免意外更新
不存储密钥
不好:
COPY .env .
# 密钥进入镜像历史
好:
# 运行时注入
docker run -e API_KEY=xxx myapp
# 或使用secrets(Swarm)
docker service create --secret api_key myapp
只安装必要的包
不好:
RUN apt-get install -y vim emacs nano wget curl
# 安装太多不必要的工具
好:
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 只安装必要的
扫描镜像漏洞
# 使用Trivy扫描漏洞
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:latest
# 使用Docker Scout(Docker内置)
docker scout quickview myapp:latest
docker scout cves myapp:latest
定期更新基础镜像
# 检查基础镜像更新
docker pull python:3.11-slim
# 重新构建镜像
docker build -t myapp:latest .
3. 性能优化
资源限制
services:
app:
image: myapp
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
启用BuildKit
# 启用BuildKit(默认已启用)
export DOCKER_BUILDKIT=1
# BuildKit优化:
# - 并行构建
# - 更好的缓存
# - 更快的构建速度
使用缓存挂载
# 使用BuildKit缓存挂载
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
多阶段构建示例
# 构建阶段
FROM golang:1.21 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 scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app /app
ENTRYPOINT ["/app"]
# 最终镜像只有几MB
4. 最佳实践
1. 遵循单一职责原则
一个镜像只做一件事:
nginx:Web服务器mysql:数据库redis:缓存
2. 最小化层数
# 合并RUN指令
RUN apt-get update && \
apt-get install -y curl wget && \
apt-get clean
# 合并ENV指令
ENV PATH=/usr/local/bin:$PATH \
TZ=Asia/Shanghai \
LANG=C.UTF-8
3. 使用健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
4. 使用信号处理
# app.py
import signal
import sys
def handle_signal(signum, frame):
print("Received signal, shutting down...")
sys.exit(0)
signal.signal(signal.SIGTERM, handle_signal)
# STOPSIGNAL设置停止信号
STOPSIGNAL SIGTERM
5. 日志处理
# 输出到stdout/stderr(Docker会自动收集)
CMD ["gunicorn", "--access-logfile", "-", "--error-logfile", "-", "app:app"]
6. 配置文件外部化
# docker-compose.yml
services:
app:
volumes:
- ./config:/app/config:ro
5. 故障排查
1. 查看容器日志
# 实时查看
docker logs -f myapp
# 查看最近100行
docker logs --tail=100 myapp
# 查看最近10分钟
docker logs --since=10m myapp
2. 进入容器排查
# 进入容器
docker exec -it myapp bash
# 查看进程
docker exec myapp ps aux
# 查看网络
docker exec myapp netstat -tuln
# 查看文件
docker exec myapp ls -la /app
3. 检查资源使用
# 查看资源使用
docker stats myapp
# 查看容器详细信息
docker inspect myapp
4. 网络排查
# 检查网络连通性
docker exec myapp ping other-container
# 检查DNS解析
docker exec myapp nslookup other-container
# 检查端口
docker exec myapp nc -zv other-container 8000
5. 常见问题
问题1:容器无法启动
# 查看日志
docker logs myapp
# 检查端口冲突
docker ps | grep 8000
# 检查资源限制
docker inspect myapp | grep -A 10 HostConfig
问题2:容器内存溢出
# 增加内存限制
docker run -m 1g myapp
# 检查内存使用
docker stats --no-stream myapp
问题3:网络不通
# 检查网络
docker network ls
docker network inspect my-network
# 检查防火墙
sudo iptables -L -n
6. 监控和告警
Prometheus监控
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
cadvisor:
image: gcr.io/cadvisor/cadvisor
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
告警配置
# alerting.yml
groups:
- name: docker_alerts
rules:
- alert: ContainerDown
expr: up{job="docker"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Container {{ $labels.name }} is down"
- alert: HighMemoryUsage
expr: container_memory_usage_bytes / container_spec_memory_limit_bytes > 0.9
for: 5m
labels:
severity: warning
annotations:
summary: "Container {{ $labels.name }} high memory usage"
7. 生产环境检查清单
部署前检查
- 镜像经过安全扫描
- 不以root用户运行
- 配置了健康检查
- 设置了资源限制
- 配置了日志收集
- 数据持久化已配置
- 网络隔离已配置
- 环境变量外部化
- 镜像版本已锁定
- 备份策略已制定
运行时检查
- 容器正常启动
- 健康检查通过
- 日志正常输出
- 资源使用正常
- 网络连通性正常
- 数据读写正常
- 监控告警正常
8. Docker vs Kubernetes
什么时候用Docker Compose?
- 单机部署
- 项目规模小
- 服务数量少(<10)
- 快速原型开发
什么时候用Kubernetes?
- 多机集群
- 大规模生产环境
- 服务数量多(>10)
- 需要自动扩缩容
- 需要高级调度
迁移路径
Docker Compose → Docker Swarm → Kubernetes
本章小结
- 镜像优化:多阶段构建、使用alpine、合并指令、清理缓存
- 安全加固:非root用户、特定版本、不存储密钥、扫描漏洞
- 性能优化:资源限制、BuildKit、缓存挂载、多阶段构建
- 最佳实践:单一职责、健康检查、信号处理、日志处理
- 故障排查:日志分析、资源监控、网络诊断
- 监控告警:Prometheus、Grafana、Alertmanager
现在已经掌握了Docker的高级技巧,可以应对90%的应用场景了!
恭喜你完成Docker教程,继续实践和探索吧!