Skip to content

Docker Compose 进阶

Docker Compose 是定义和运行多容器 Docker 应用程序的工具。本文档介绍 Docker Compose 的高级特性和最佳实践。

🎯 Compose 进阶概念

Compose 文件版本

yaml
# 推荐使用最新版本
version: '3.8'

# 或者省略版本(使用最新版本)
services:
  web:
    image: nginx

服务依赖管理

yaml
services:
  web:
    image: nginx
    depends_on:
      - api
      - db
    
  api:
    image: my-api
    depends_on:
      - db
      - redis
    
  db:
    image: postgres:15
    
  redis:
    image: redis:alpine

健康检查依赖

yaml
services:
  web:
    image: nginx
    depends_on:
      db:
        condition: service_healthy
    
  db:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

🔧 高级配置

环境变量管理

yaml
# .env 文件
POSTGRES_VERSION=15
POSTGRES_PASSWORD=secret123
API_PORT=3000
NODE_ENV=production

# docker-compose.yml
services:
  db:
    image: postgres:${POSTGRES_VERSION}
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    
  api:
    build: .
    ports:
      - "${API_PORT}:3000"
    environment:
      - NODE_ENV=${NODE_ENV}
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@db:5432/myapp

多环境配置

yaml
# docker-compose.yml (基础配置)
services:
  web:
    image: nginx
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    
  api:
    build: .
    environment:
      - NODE_ENV=development

# docker-compose.prod.yml (生产环境覆盖)
services:
  web:
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    
  api:
    environment:
      - NODE_ENV=production
    deploy:
      replicas: 2
bash
# 使用多个 compose 文件
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

扩展和继承

yaml
# docker-compose.base.yml
x-common-variables: &common-variables
  POSTGRES_USER: postgres
  POSTGRES_PASSWORD: password

x-logging: &default-logging
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"

services:
  db:
    image: postgres:15
    environment:
      <<: *common-variables
      POSTGRES_DB: myapp
    logging: *default-logging
    
  api:
    build: .
    environment:
      <<: *common-variables
      DATABASE_URL: postgresql://postgres:password@db:5432/myapp
    logging: *default-logging

🌐 网络配置

自定义网络

yaml
services:
  web:
    image: nginx
    networks:
      - frontend
      - backend
    
  api:
    image: my-api
    networks:
      - backend
      - database
    
  db:
    image: postgres:15
    networks:
      - database

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
  database:
    driver: bridge
    internal: true  # 内部网络,无法访问外网

网络别名

yaml
services:
  api:
    image: my-api
    networks:
      backend:
        aliases:
          - api-server
          - backend-api
    
  worker:
    image: my-worker
    networks:
      - backend
    # worker 可以通过 api-server 或 backend-api 访问 api 服务

networks:
  backend:

外部网络

yaml
services:
  web:
    image: nginx
    networks:
      - default
      - external-network

networks:
  external-network:
    external: true
    name: my-existing-network

💾 存储管理

命名卷

yaml
services:
  db:
    image: postgres:15
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - postgres-config:/etc/postgresql
    
  backup:
    image: my-backup-tool
    volumes:
      - postgres-data:/backup/source:ro
      - backup-storage:/backup/destination

volumes:
  postgres-data:
    driver: local
    driver_opts:
      type: ext4
      device: /dev/sdb1
  postgres-config:
  backup-storage:
    external: true

绑定挂载

yaml
services:
  web:
    image: nginx
    volumes:
      - type: bind
        source: ./nginx.conf
        target: /etc/nginx/nginx.conf
        read_only: true
      - type: bind
        source: ./logs
        target: /var/log/nginx
        bind:
          propagation: shared

tmpfs 挂载

yaml
services:
  cache:
    image: redis:alpine
    tmpfs:
      - /tmp:rw,noexec,nosuid,size=100m
      - /var/cache/redis:rw,size=50m

🔒 安全配置

用户和权限

yaml
services:
  app:
    image: my-app
    user: "1000:1000"  # 非 root 用户
    
  db:
    image: postgres:15
    user: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

资源限制

yaml
services:
  api:
    image: my-api
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M
    
  db:
    image: postgres:15
    deploy:
      resources:
        limits:
          memory: 2G
        reservations:
          memory: 1G

安全选项

yaml
services:
  app:
    image: my-app
    security_opt:
      - no-new-privileges:true
      - apparmor:my-profile
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    read_only: true
    tmpfs:
      - /tmp:rw,noexec,nosuid

📊 监控和日志

健康检查

yaml
services:
  web:
    image: nginx
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    
  api:
    image: my-api
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      retries: 3

日志配置

yaml
services:
  web:
    image: nginx
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
        labels: "service=web"
    
  api:
    image: my-api
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://192.168.1.100:514"
        tag: "api-service"

🚀 部署策略

滚动更新

yaml
services:
  api:
    image: my-api:${VERSION}
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
        order: start-first
      rollback_config:
        parallelism: 1
        delay: 5s
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3

蓝绿部署

bash
#!/bin/bash
# blue-green-deploy.sh

# 部署绿色环境
docker-compose -f docker-compose.yml -f docker-compose.green.yml up -d

# 健康检查
./health-check.sh green

# 切换流量
./switch-traffic.sh green

# 停止蓝色环境
docker-compose -f docker-compose.yml -f docker-compose.blue.yml down

🔧 开发工具集成

开发环境配置

yaml
# docker-compose.dev.yml
services:
  api:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - ./src:/app/src:cached
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DEBUG=*
    ports:
      - "3000:3000"
      - "9229:9229"  # Node.js 调试端口
    
  db:
    image: postgres:15
    ports:
      - "5432:5432"  # 暴露端口用于开发调试

测试环境

yaml
# docker-compose.test.yml
services:
  api:
    build: .
    environment:
      - NODE_ENV=test
      - DATABASE_URL=postgresql://postgres:password@test-db:5432/test
    depends_on:
      - test-db
    
  test-db:
    image: postgres:15
    environment:
      POSTGRES_DB: test
      POSTGRES_PASSWORD: password
    tmpfs:
      - /var/lib/postgresql/data  # 使用内存存储提高测试速度

📈 性能优化

构建优化

yaml
services:
  api:
    build:
      context: .
      dockerfile: Dockerfile
      cache_from:
        - my-api:latest
      args:
        - NODE_ENV=production
        - BUILD_DATE=${BUILD_DATE}

资源优化

yaml
services:
  web:
    image: nginx:alpine  # 使用轻量级镜像
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 256M
    
  cache:
    image: redis:alpine
    command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru

🛠️ 实用脚本

管理脚本

bash
#!/bin/bash
# manage.sh

case "$1" in
  start)
    docker-compose up -d
    ;;
  stop)
    docker-compose down
    ;;
  restart)
    docker-compose restart
    ;;
  logs)
    docker-compose logs -f ${2:-}
    ;;
  scale)
    docker-compose up -d --scale ${2}=${3}
    ;;
  backup)
    docker-compose exec db pg_dump -U postgres myapp > backup.sql
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|logs|scale|backup}"
    exit 1
    ;;
esac

健康检查脚本

bash
#!/bin/bash
# health-check.sh

services=("web" "api" "db")

for service in "${services[@]}"; do
  if docker-compose ps $service | grep -q "Up (healthy)"; then
    echo "✅ $service is healthy"
  else
    echo "❌ $service is not healthy"
    exit 1
  fi
done

echo "🎉 All services are healthy"

通过这些高级特性和最佳实践,您可以构建更加健壮、可维护和可扩展的多容器应用程序。