正在加载,请稍候…

Docker Compose 生产环境实战:多服务应用、健康检查与密钥管理

学习如何在生产环境中使用 Docker Compose,涵盖健康检查、密钥管理、资源限制、自定义网络、卷管理和滚动部署等关键配置。

Docker Compose 生产环境实战:多服务应用、健康检查与密钥管理

Docker Compose 生产环境实战

虽然 Kubernetes 擅长处理大规模部署,但 Docker Compose 对于中小型生产工作负载同样表现出色。本指南将介绍生产级配置。

生产就绪的 docker-compose.yml

services:
  api:
    image: myapp/api:${TAG:-latest}
    restart: unless-stopped
    
    # 资源限制
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 512M
        reservations:
          memory: 256M
      replicas: 2
    
    # 健康检查
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    
    environment:
      NODE_ENV: production
      PORT: 3000
    
    # 密钥(不在环境变量中!)
    secrets:
      - db_password
      - jwt_secret
    
    networks:
      - frontend
      - backend
    
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  postgres:
    image: postgres:15-alpine
    restart: unless-stopped
    
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5
    
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    
    secrets:
      - db_password
    
    networks:
      - backend

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --appendonly yes --requirepass-file /run/secrets/redis_password
    
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
    
    volumes:
      - redis_data:/data
    
    secrets:
      - redis_password
    
    networks:
      - backend

  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    networks:
      - frontend
    depends_on:
      - api

secrets:
  db_password:
    file: ./secrets/db_password.txt
  jwt_secret:
    file: ./secrets/jwt_secret.txt
  redis_password:
    file: ./secrets/redis_password.txt

volumes:
  postgres_data:
  redis_data:

networks:
  frontend:
  backend:
    internal: true  # 外部不可访问

Docker Compose 生产环境实战:多服务应用、健康检查与密钥管理 插图

在应用中读取密钥

// Node.js: 从 /run/secrets/ 读取 Docker 密钥
const fs = require('fs');

function getSecret(name) {
  const secretPath = `/run/secrets/${name}`;
  try {
    return fs.readFileSync(secretPath, 'utf8').trim();
  } catch {
    // 本地开发时回退到环境变量
    return process.env[name.toUpperCase()];
  }
}

const config = {
  dbPassword: getSecret('db_password'),
  jwtSecret: getSecret('jwt_secret'),
};

滚动更新

# 拉取新镜像
docker compose pull api

# 滚动重启(每次更新一个副本)
docker compose up -d --no-deps --scale api=2 api

# 或使用更新顺序
docker compose up -d api
# Compose 会在新容器健康后停止旧容器

Docker Compose 生产环境实战:多服务应用、健康检查与密钥管理 插图

备份与恢复

# 备份 PostgreSQL
docker compose exec postgres pg_dump -U myapp myapp | gzip > backup-$(date +%Y%m%d).sql.gz

# 恢复
gunzip -c backup-20240101.sql.gz | docker compose exec -T postgres psql -U myapp myapp

# 备份卷
docker run --rm \
  -v myapp_postgres_data:/data \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/postgres-$(date +%Y%m%d).tar.gz /data

环境特定覆盖

# docker-compose.override.yml(开发环境自动加载)
services:
  api:
    build: .  # 开发时从源码构建
    volumes:
      - .:/app  # 热重载
    environment:
      NODE_ENV: development
    ports:
      - "9229:9229"  # 调试端口
  
  postgres:
    ports:
      - "5432:5432"  # 开发时暴露端口
# 生产环境:显式指定文件
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# 开发环境:自动使用覆盖文件
docker compose up -d

Docker Compose 生产环境实战:多服务应用、健康检查与密钥管理 插图

使用 Compose 进行监控

# 添加 Prometheus + Grafana
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    networks:
      - backend

  grafana:
    image: grafana/grafana
    ports:
      - "3001:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD_FILE: /run/secrets/grafana_password
    secrets:
      - grafana_password
    networks:
      - backend

总结

生产环境 Docker Compose 模式:

  • 始终使用健康检查进行依赖排序
  • 将密钥存储为文件,而非环境变量
  • 使用内部网络隔离后端服务
  • 设置资源限制以防止容器资源耗尽
  • 使用环境特定的覆盖文件
  • 对有状态服务自动化备份