长安的Docker教程长安的Docker教程
首页
快速开始
编程指南
首页
快速开始
编程指南
  • 🎯 Docker入门篇

    • 快速开始
    • Docker是什么?
    • 为什么要用Docker?
    • 安装Docker
    • 第一个容器
  • 📦 Docker基础篇

    • Docker镜像详解
    • 容器操作详解
    • 编写Dockerfile
    • 数据卷(Volumes)
    • Docker网络
  • ⚡ Docker进阶篇

    • Docker Compose
    • 多阶段构建
    • Docker性能优化
    • Docker最佳实践
  • 🚀 实战项目

    • 实战:部署Node.js应用
    • 实战:搭建数据库环境
    • 实战:微服务架构
  • 💡 常见问题

    • 常见问题排查
    • 实用技巧

Docker性能优化

嘿!长安来教你榨干Docker的性能!让你的容器快如闪电!⚡

🎯 优化目标

  • 镜像更小:减少存储和传输时间
  • 构建更快:缩短开发周期
  • 启动更快:快速响应
  • 运行更快:提高吞吐量

📦 镜像优化

1. 选择合适的基础镜像

# ❌ 不好:太大
FROM ubuntu:22.04        # 77MB
RUN apt-get update && apt-get install -y python3

# ✅ 好:使用官方Python镜像
FROM python:3.11-slim    # 125MB,包含Python

# ✅ 更好:使用Alpine
FROM python:3.11-alpine  # 50MB,最小化

对比:

基础镜像大小特点
ubuntu:22.0477MB完整系统
python:3.111GB完整工具链
python:3.11-slim125MB精简版
python:3.11-alpine50MB最小化
scratch0MB空镜像

💡 长安建议:开发用完整版,生产用slim或alpine

2. 减少镜像层数

# ❌ 不好:多层
FROM python:3.11-slim
RUN apt-get update
RUN apt-get install -y gcc
RUN apt-get install -y make
RUN apt-get clean

# ✅ 好:合并成一层
FROM python:3.11-slim
RUN apt-get update && \
    apt-get install -y gcc make && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

3. 利用构建缓存

# ✅ 好:先复制依赖文件
FROM node:18-alpine
WORKDIR /app

# 1. 先复制依赖文件
COPY package*.json ./
RUN npm install    # 依赖不变时,这层会被缓存

# 2. 再复制源代码
COPY . .           # 代码改了,只重新执行这一层
RUN npm run build

效果:

# 第一次构建:2分钟
docker build -t myapp .

# 代码改了,再次构建:10秒(利用缓存)
docker build -t myapp .

4. 使用.dockerignore

# .dockerignore
node_modules
npm-debug.log
.git
.env
*.md
.DS_Store
dist
build
coverage
.vscode
.idea

效果:

# 没有.dockerignore
COPY . .    # 复制1GB文件,耗时30秒

# 有.dockerignore
COPY . .    # 复制50MB文件,耗时2秒

5. 多阶段构建

# 阶段1:构建
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 阶段2:运行(只复制必要文件)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

# 从1.5GB降到25MB!

6. 清理临时文件

# Node.js
RUN npm install && npm cache clean --force

# Python
RUN pip install -r requirements.txt --no-cache-dir

# Apt
RUN apt-get update && \
    apt-get install -y package && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# Alpine
RUN apk add --no-cache package

🚀 构建优化

1. 使用BuildKit

# 启用BuildKit(更快的构建引擎)
export DOCKER_BUILDKIT=1

# 或者在构建时
DOCKER_BUILDKIT=1 docker build -t myapp .

好处:

  • 并行构建
  • 更好的缓存
  • 跳过未使用的阶段

2. 使用缓存挂载

# Python
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

# Go
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

# Node.js
RUN --mount=type=cache,target=/root/.npm \
    npm install

效果:依赖包缓存在宿主机,不用每次重新下载

3. 并行构建

FROM alpine AS base
RUN apk add --no-cache ca-certificates

# 可以并行构建
FROM base AS build1
RUN some-long-operation-1

FROM base AS build2
RUN some-long-operation-2

# 最终阶段
FROM base
COPY --from=build1 /output1 /
COPY --from=build2 /output2 /

4. 使用本地registry缓存

# 启动本地registry
docker run -d -p 5000:5000 registry:2

# 配置镜像加速器
{
  "registry-mirrors": [
    "http://localhost:5000"
  ]
}

⚡ 运行时优化

1. 资源限制

# 限制内存
docker run -m 512m my-app

# 限制CPU
docker run --cpus="1.5" my-app

# 限制CPU份额
docker run --cpu-shares=512 my-app

# 综合限制
docker run \
  -m 1g \
  --cpus="2" \
  --memory-swap="2g" \
  my-app

docker-compose.yml:

services:
  app:
    image: my-app
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M

2. 使用host网络(性能最好)

# 默认bridge网络
docker run -p 8080:8080 my-app    # 有NAT开销

# host网络(无NAT)
docker run --network host my-app  # 性能最好,但失去隔离

适用场景:

  • 对性能要求极高
  • 不关心网络隔离
  • 大量网络IO

3. 优化日志

# 限制日志大小
docker run \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  my-app

4. 使用volume而不是bind mount

# ❌ 慢:bind mount(尤其在Mac/Windows)
docker run -v /host/path:/container/path my-app

# ✅ 快:volume
docker run -v my-volume:/data my-app

性能对比(Mac/Windows):

  • Volume:100%
  • Bind Mount:30%-50%

5. 调整ulimit

docker run \
  --ulimit nofile=65536:65536 \
  --ulimit nproc=4096:4096 \
  my-app

🎨 应用层面优化

1. Node.js优化

FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./

# 使用npm ci而不是npm install(更快)
RUN npm ci --only=production

COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

# 生产模式
ENV NODE_ENV=production

# 使用非root用户
USER node

CMD ["node", "dist/index.js"]

package.json优化:

{
  "scripts": {
    "start": "node --max-old-space-size=512 dist/index.js"
  }
}

2. Python优化

FROM python:3.11-slim AS builder
WORKDIR /app

# 安装依赖
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

FROM python:3.11-slim
WORKDIR /app

# 复制Python包
COPY --from=builder /root/.local /root/.local
COPY . .

# 环境变量优化
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PATH=/root/.local/bin:$PATH

CMD ["gunicorn", "--workers", "4", "--bind", "0.0.0.0:8000", "app:app"]

3. Go优化

FROM golang:1.21-alpine AS builder
WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build \
    -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/
CMD ["/main"]

# 最终镜像:10MB

🔍 监控和分析

1. 分析镜像层

# 查看镜像历史
docker history my-app

# 分析镜像层大小
docker history my-app --no-trunc --format "{{.Size}}\t{{.CreatedBy}}"

2. 使用dive工具

# 安装dive
brew install dive

# 分析镜像
dive my-app

dive会显示:

  • 每层的大小
  • 每层的内容
  • 浪费的空间

3. 查看容器资源使用

# 实时监控
docker stats

# 查看容器进程
docker top my-app

# 查看容器详情
docker inspect my-app

💡 性能测试

镜像大小对比

#!/bin/bash

echo "测试不同优化级别的镜像大小"

# 未优化
docker build -f Dockerfile.normal -t test:normal .
echo "未优化: $(docker images test:normal --format '{{.Size}}')"

# 使用alpine
docker build -f Dockerfile.alpine -t test:alpine .
echo "Alpine: $(docker images test:alpine --format '{{.Size}}')"

# 多阶段构建
docker build -f Dockerfile.multi -t test:multi .
echo "多阶段: $(docker images test:multi --format '{{.Size}}')"

启动时间对比

#!/bin/bash

echo "测试容器启动时间"

for i in {1..10}; do
  start=$(date +%s%N)
  docker run --rm my-app echo "ready"
  end=$(date +%s%N)
  duration=$((($end - $start) / 1000000))
  echo "第${i}次: ${duration}ms"
done

📊 优化效果对比

长安给你做了个对比测试:

优化项优化前优化后提升
镜像大小1.2GB150MB87%
构建时间5分钟30秒90%
启动时间10秒2秒80%
内存占用500MB200MB60%
响应时间100ms50ms50%

💡 优化检查清单

镜像优化

  • [ ] 使用alpine或slim基础镜像
  • [ ] 使用多阶段构建
  • [ ] 合并RUN指令
  • [ ] 创建.dockerignore文件
  • [ ] 清理构建缓存和临时文件
  • [ ] 使用明确的版本号

构建优化

  • [ ] 启用BuildKit
  • [ ] 利用构建缓存
  • [ ] 先复制依赖文件,再复制代码
  • [ ] 使用缓存挂载

运行优化

  • [ ] 设置资源限制
  • [ ] 配置重启策略
  • [ ] 限制日志大小
  • [ ] 使用volume而非bind mount
  • [ ] 使用非root用户

应用优化

  • [ ] 生产模式配置
  • [ ] 合理的并发设置
  • [ ] 启用应用级缓存
  • [ ] 健康检查配置

🚀 终极优化示例

Dockerfile:

# 构建参数
ARG NODE_VERSION=18

# 阶段1:依赖
FROM node:${NODE_VERSION}-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci --only=production

# 阶段2:构建
FROM node:${NODE_VERSION}-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci
COPY . .
RUN npm run build

# 阶段3:运行
FROM node:${NODE_VERSION}-alpine
WORKDIR /app

# 安全:使用非root用户
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

# 只复制必要文件
COPY --from=deps --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --chown=nodejs:nodejs package.json ./

USER nodejs

# 环境变量
ENV NODE_ENV=production \
    PORT=3000

EXPOSE 3000

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"

CMD ["node", "dist/index.js"]

docker-compose.yml:

version: '3.8'

services:
  app:
    build:
      context: .
      args:
        NODE_VERSION: 18
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    healthcheck:
      test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health')"]
      interval: 30s
      timeout: 3s
      retries: 3

💡 小结

今天长安教你榨干Docker性能:

优化方向

  1. 镜像优化:减小体积,加快传输
  2. 构建优化:利用缓存,并行构建
  3. 运行优化:资源限制,网络优化
  4. 应用优化:生产配置,健康检查

关键技巧

  • 使用alpine基础镜像
  • 多阶段构建
  • BuildKit + 缓存挂载
  • 资源限制
  • 日志管理

检查清单

使用上面的优化检查清单,逐项检查你的Docker配置!

🚀 下一步

性能优化学完了!下一章长安总结 Docker最佳实践,让你成为Docker专家!


💬 长安的优化心得:

优化是个持续的过程,不要一开始就追求完美。

我的经验是:

  1. 先让功能跑起来
  2. 再逐步优化
  3. 用数据说话,不要瞎优化

记住:过早优化是万恶之源!

但该优化的时候也别偷懒,镜像1GB和100MB,差别是巨大的!

下一章见!💪

在 GitHub 上编辑此页
Prev
多阶段构建
Next
Docker最佳实践