跳轉到內容

Docker Compose 高級配置與多服務編排實戰 2026 | 容器編排完全指南

Docker Compose 高級配置與多服務編排

Docker Compose 是定義和運行多容器 Docker 應用程序的工具。從簡單的開發環境到複雜的生產部署,Compose 都能勝任。本文將深入 Compose 的高級特性,從環境變量管理到滾動更新,全面掌握容器編排技能。


一、Compose 文件結構

1.1 Compose 版本與基本結構

yaml
# docker-compose.yml
version: '3.8'

services:
  web:
    build: .
    ports:
      - "80:80"
    depends_on:
      - db
      - redis

  db:
    image: postgres:15
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine

volumes:
  pgdata:

networks:
  default:
    name: my-network

1.2 常用配置項速查

配置項說明
image使用的鏡像
build構建鏡像的上下文
ports端口映射
volumes數據卷掛載
environment環境變量
env_file環境變量文件
depends_on服務依賴
networks網絡配置
healthcheck健康檢查
restart重啟策略
deploy部署配置(Swarm)
command覆蓋啟動命令
entrypoint覆蓋入口點

二、環境變量管理

2.1 多種環境變量方式

yaml
# 方式1:直接在 docker-compose.yml 中定義
services:
  web:
    image: nginx
    environment:
      - NODE_ENV=production
      - API_URL=https://api.example.com
      - DEBUG=false

# 方式2:鍵值對格式
services:
  web:
    image: nginx
    environment:
      NODE_ENV: production
      API_URL: https://api.example.com

2.2 使用 .env 文件

bash
# .env
NODE_ENV=production
API_URL=https://api.example.com
DB_PASSWORD=secret123
REDIS_URL=redis://redis:6379
yaml
# docker-compose.yml
services:
  web:
    image: myapp
    env_file:
      - .env

2.3 多環境配置

yaml
# docker-compose.base.yml - 基礎配置
services:
  web:
    build: .
    volumes:
      - ./src:/app/src
yaml
# docker-compose.dev.yml - 開發環境
services:
  web:
    environment:
      - NODE_ENV=development
      - DEBUG=true
    ports:
      - "3000:3000"
    command: npm run dev

  db:
    image: postgres:15
    ports:
      - "5432:5432"
yaml
# docker-compose.prod.yml - 生產環境
services:
  web:
    environment:
      - NODE_ENV=production
    ports:
      - "80:3000"
    restart: always
    deploy:
      replicas: 3
bash
# 啟動開發環境
docker-compose -f docker-compose.base.yml -f docker-compose.dev.yml up -d

# 啟動生產環境
docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml up -d

2.4 變量替換

yaml
services:
  web:
    image: myapp:${VERSION:-latest}
    ports:
      - "${WEB_PORT:-8080}:3000"
    environment:
      - DB_HOST=${DB_HOST:-db}

三、網絡配置

3.1 自定義網絡

yaml
services:
  frontend:
    image: nginx
    networks:
      - frontend
      - backend

  api:
    image: myapi
    networks:
      - backend
      - database

  db:
    image: postgres
    networks:
      - database

networks:
  frontend:
    name: frontend-net
    driver: bridge

  backend:
    name: backend-net
    driver: bridge

  database:
    name: database-net
    driver: bridge
    internal: true  # 內部網絡,無法訪問外網

3.2 網絡別名

yaml
services:
  web:
    image: nginx
    networks:
      frontend:
        aliases:
          - webserver
          - nginx-server

  app:
    image: myapp
    networks:
      backend:
        aliases:
          - api-server

3.3 主機網絡模式

yaml
services:
  monitoring:
    image: prom/prometheus
    network_mode: host  # 使用主機網絡
    pid: host           # 使用主機 PID 命名空間

四、數據持久化

4.1 命名卷(推薦)

yaml
services:
  db:
    image: postgres:15
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
    name: postgres-data
    driver: local

  redis_data:
    name: redis-data
    driver: local

4.2 綁定掛載

yaml
services:
  web:
    image: nginx
    volumes:
      # 配置文件
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      # 靜態文件
      - ./static:/usr/share/nginx/html:ro
      # 日誌
      - ./logs:/var/log/nginx

  app:
    image: myapp
    volumes:
      # 源代碼(開發用)
      - ./src:/app/src
      # 上傳文件
      - ./uploads:/app/uploads

4.3 tmpfs(內存文件系統)

yaml
services:
  cache:
    image: redis:7
    tmpfs:
      - /tmp
      - /var/run

4.4 卷的備份與恢復

bash
# 備份數據卷
docker run --rm \
  -v postgres-data:/data \
  -v $(pwd)/backup:/backup \
  alpine tar czf /backup/postgres-backup.tar.gz /data

# 恢復數據卷
docker run --rm \
  -v postgres-data:/data \
  -v $(pwd)/backup:/backup \
  alpine tar xzf /backup/postgres-backup.tar.gz -C /

五、健康檢查

5.1 HTTP 健康檢查

yaml
services:
  web:
    image: nginx
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

5.2 TCP 健康檢查

yaml
services:
  db:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  redis:
    image: redis:7
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

5.3 自定義健康檢查腳本

yaml
services:
  app:
    build: .
    healthcheck:
      test: ["CMD-SHELL", "node /app/scripts/healthcheck.js"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 15s
javascript
// scripts/healthcheck.js
const http = require('http')

const options = {
  hostname: 'localhost',
  port: 3000,
  path: '/health',
  method: 'GET'
}

const req = http.request(options, (res) => {
  process.exit(res.statusCode === 200 ? 0 : 1)
})

req.on('error', () => {
  process.exit(1)
})

req.end()

5.4 服務依賴與健康檢查

yaml
services:
  web:
    image: myapp
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
      cache:
        condition: service_started

  db:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      retries: 5

  redis:
    image: redis:7
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      retries: 3

六、資源限制與性能調優

6.1 CPU 和內存限制

yaml
services:
  web:
    image: nginx
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 1G
        reservations:
          cpus: '1.0'
          memory: 512M

6.2 ulimit 調優

yaml
services:
  nginx:
    image: nginx
    ulimits:
      nofile:
        soft: 65536
        hard: 65536
      nproc: 65535

6.3 重啟策略

yaml
services:
  web:
    image: nginx
    restart: unless-stopped  # always | unless-stopped | on-failure | no

  worker:
    image: my-worker
    restart: on-failure:5  # 失敗最多重啟 5 次

七、多服務編排實戰

7.1 完整 Web 應用棧

yaml
# docker-compose.yml
version: '3.8'

services:
  # Nginx 反向代理
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
      - ./logs/nginx:/var/log/nginx
    depends_on:
      - web
      - api
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - frontend
      - backend

  # 前端應用
  web:
    image: my-web-app:latest
    build:
      context: ./web
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - API_BASE_URL=https://api.example.com
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:3000"]
      interval: 30s
      retries: 3
    networks:
      - backend

  # API 服務
  api:
    image: my-api:latest
    build:
      context: ./api
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_PORT=5432
      - REDIS_HOST=redis
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:3001/health"]
      interval: 30s
      retries: 3
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
    networks:
      - backend
      - database

  # PostgreSQL 數據庫
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./postgres/init:/docker-entrypoint-initdb.d:ro
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - database

  # Redis 緩存
  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3
    networks:
      - database

volumes:
  postgres_data:
  redis_data:

networks:
  frontend:
    name: frontend-net
  backend:
    name: backend-net
  database:
    name: database-net
    internal: true

7.2 啟動順序與依賴管理

bash
# 查看服務啟動順序
docker-compose config --services

# 只啟動某個服務及其依賴
docker-compose up -d web

# 查看服務狀態
docker-compose ps

# 查看服務日誌
docker-compose logs -f web

# 重啟某個服務
docker-compose restart api

# 縮容/擴容
docker-compose up -d --scale api=3

八、生產環境部署

8.1 滾動更新

yaml
services:
  web:
    image: myapp:latest
    deploy:
      replicas: 3
      update_config:
        parallelism: 1        # 每次更新 1 個
        delay: 10s             # 間隔時間
        failure_action: rollback  # 失敗回滾
        monitor: 30s           # 監控時間
        max_failure_ratio: 0.3  # 最大失敗率
      rollback_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
      resources:
        limits:
          cpus: '2.0'
          memory: 1G
        reservations:
          cpus: '1.0'
          memory: 512M

8.2 零停機部署

bash
# 構建新版本鏡像
docker build -t myapp:v2 .

# 更新鏡像標籤
docker tag myapp:v2 myapp:latest

# 觸發滾動更新
docker-compose up -d --no-deps web

# 查看更新進度
docker-compose ps
docker-compose logs -f web

8.3 藍綠部署

yaml
# docker-compose.blue.yml - 藍色環境
services:
  web-blue:
    image: myapp:v1
    ports:
      - "8080:3000"
yaml
# docker-compose.green.yml - 綠色環境
services:
  web-green:
    image: myapp:v2
    ports:
      - "8081:3000"
bash
# 1. 部署綠色環境
docker-compose -f docker-compose.green.yml up -d

# 2. 驗證綠色環境正常
curl http://localhost:8081/health

# 3. 切換流量(更新 Nginx 配置指向綠色環境)
# 4. 停止藍色環境
docker-compose -f docker-compose.blue.yml down

九、常用命令與技巧

9.1 日常管理命令

bash
# 啟動服務
docker-compose up -d
docker-compose up -d --build  # 構建後啟動
docker-compose up -d --force-recreate  # 強制重建

# 停止服務
docker-compose stop
docker-compose down
docker-compose down -v  # 刪除數據卷

# 查看狀態
docker-compose ps
docker-compose logs
docker-compose logs -f web
docker-compose logs --tail=100

# 進入容器
docker-compose exec web bash
docker-compose exec db psql -U postgres

# 查看配置
docker-compose config
docker-compose config --services
docker-compose config --volumes

9.2 清理與維護

bash
# 刪除未使用的鏡像
docker image prune

# 刪除未使用的容器
docker container prune

# 刪除未使用的數據卷
docker volume prune

# 一鍵清理
docker system prune -a

# 查看磁盤使用
docker system df

9.3 調試技巧

bash
# 查看容器啟動日誌
docker-compose logs web --no-log-prefix

# 查看實時資源使用
docker stats

# 進入容器調試
docker-compose exec web sh

# 複製文件到容器
docker cp ./local-file.txt mycontainer:/app/

# 從容器複製文件
docker cp mycontainer:/app/file.txt ./local/

十、最佳實踐

10.1 配置管理

  1. 使用多文件配置:基礎配置 + 環境配置
  2. 敏感信息用 .env:不要提交到版本控制
  3. 使用變量替換:提高配置靈活性
  4. 配置文件分層:common / dev / staging / prod

10.2 安全建議

  1. 最小權限原則:容器以非 root 用戶運行
  2. 只讀文件系統read_only: true
  3. 不暴露不必要的端口:只暴露需要的端口
  4. 使用內部網絡:數據庫等放在內部網絡

10.3 性能優化

  1. 合理設置資源限制:避免資源爭搶
  2. 使用命名卷:性能優於綁定掛載
  3. 健康檢查:及時發現故障
  4. 多副本部署:提高可用性

十一、總結

  • ✅ 掌握 Compose 文件結構與常用配置
  • ✅ 環境變量管理與多環境配置
  • ✅ 網絡配置(自定義網絡、別名、內部網絡)
  • ✅ 數據持久化(命名卷、綁定掛載、備份恢復)
  • ✅ 健康檢查與服務依賴
  • ✅ 資源限制與性能調優
  • ✅ 多服務編排實戰(完整 Web 應用棧)
  • ✅ 生產環境部署(滾動更新、藍綠部署)
  • ✅ 常用命令與調試技巧

Docker Compose 是容器編排的入門利器,掌握這些高級配置技巧,讓你能夠輕鬆管理複雜的多容器應用。


相關閱讀:

最後更新於: