Docker_Compose进阶

一、高级服务配置

1.1 资源限制

1.1.1 CPU限制

CPU配置:

version: '3.8'

services:
  app:
    image: myapp:latest
    deploy:
      resources:
        limits:
          cpus: '0.50'    # 最多使用50%的CPU
        reservations:
          cpus: '0.25'    # 预留25%的CPU

CPU配置说明:

CPU限制:
├─ cpus: CPU核心数
│   ├─ '0.50': 50%的CPU
│   ├─ '1.00': 1个CPU核心
│   └─ '2.00': 2个CPU核心
│
├─ limits: 最大限制
│   └─ 容器最多使用的CPU
│
└─ reservations: 预留资源
    └─ 容器最少需要的CPU

使用场景:
├─ 开发环境: 不限制
├─ 测试环境: 适度限制
└─ 生产环境: 严格限制

1.1.2 内存限制

内存配置:

version: '3.8'

services:
  app:
    image: myapp:latest
    deploy:
      resources:
        limits:
          memory: 512M    # 最多使用512M内存
        reservations:
          memory: 256M    # 预留256M内存

内存配置说明:

内存限制:
├─ memory: 内存大小
│   ├─ '256M': 256MB
│   ├─ '512M': 512MB
│   ├─ '1G': 1GB
│   └─ '2G': 2GB
│
├─ limits: 最大限制
│   └─ 容器最多使用的内存
│
└─ reservations: 预留资源
    └─ 容器最少需要的内存

注意事项:
├─ 内存限制不能小于预留内存
├─ 超过限制会触发OOM Killer
└─ 建议设置合理的内存限制

1.1.3 完整资源限制

综合配置:

version: '3.8'

services:
  app:
    image: myapp:latest
    deploy:
      resources:
        limits:
          cpus: '1.00'
          memory: 1G
        reservations:
          cpus: '0.50'
          memory: 512M
      # 重启策略
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
      # 副本数量
      replicas: 3
      # 更新配置
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
      # 回滚配置
      rollback_config:
        parallelism: 1
        delay: 10s

1.2 健康检查

1.2.1 健康检查配置

基本配置:

version: '3.8'

services:
  web:
    image: nginx:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:80"]
      interval: 30s      # 检查间隔
      timeout: 10s       # 超时时间
      retries: 3         # 重试次数
      start_period: 40s  # 启动等待时间

健康检查说明:

健康检查参数:
├─ test: 检查命令
│   ├─ CMD: 执行命令
│   ├─ CMD-SHELL: 执行Shell命令
│   └─ NONE: 禁用健康检查
│
├─ interval: 检查间隔
│   └─ 默认30秒
│
├─ timeout: 超时时间
│   └─ 默认30秒
│
├─ retries: 重试次数
│   └─ 默认3次
│
└─ start_period: 启动等待时间
    └─ 默认0秒

健康状态:
├─ starting: 启动中
├─ healthy: 健康
├─ unhealthy: 不健康
└─ none: 未配置

1.2.2 不同服务的健康检查

MySQL健康检查:

services:
  mysql:
    image: mysql:5.7
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

Redis健康检查:

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

应用健康检查:

services:
  app:
    image: myapp:latest
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

1.3 日志配置

1.3.1 日志驱动配置

日志配置:

version: '3.8'

services:
  app:
    image: myapp:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"    # 单个日志文件最大10M
        max-file: "3"      # 最多保留3个日志文件
        labels: "app,env"  # 添加标签
        tag: "{{.Name}}/{{.ID}}"  # 日志标签

日志驱动说明:

日志驱动类型:
├─ json-file: 默认驱动
│   ├─ 日志以JSON格式存储
│   ├─ 支持日志轮转
│   └─ 适合大多数场景
│
├─ syslog: 系统日志
│   ├─ 发送到syslog守护进程
│   └─ 适合集中日志管理
│
├─ journald: systemd日志
│   ├─ 发送到journald
│   └─ 适合systemd系统
│
├─ none: 禁用日志
│   └─ 不记录日志
│
└─ fluentd: Fluentd日志
    ├─ 发送到Fluentd
    └─ 适合日志收集

日志轮转选项:
├─ max-size: 单个日志文件最大大小
├─ max-file: 最多保留的日志文件数
└─ 建议配置日志轮转

1.3.2 不同日志驱动示例

Syslog配置:

services:
  app:
    image: myapp:latest
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://192.168.1.100:514"
        syslog-facility: "daemon"
        tag: "myapp"

Fluentd配置:

services:
  app:
    image: myapp:latest
    logging:
      driver: "fluentd"
      options:
        fluentd-address: "localhost:24224"
        fluentd-async: "true"
        tag: "docker.{{.Name}}"

二、服务扩展与负载均衡

2.1 服务扩展

2.1.1 手动扩展

docker compose scale:

# 扩展服务到3个副本
docker compose up -d --scale web=3

# 查看服务状态
docker compose ps

# 输出
NAME                COMMAND                  SERVICE             STATUS              PORTS
myapp-web-1         "nginx -g 'daemon of…"   web                 running             
myapp-web-2         "nginx -g 'daemon of…"   web                 running             
myapp-web-3         "nginx -g 'daemon of…"   web                 running

注意事项:

服务扩展限制:
├─ 端口冲突: 不能映射固定端口
│   └─ 使用随机端口或负载均衡
│
├─ 数据卷: 共享数据卷
│   └─ 注意并发访问
│
└─ 网络: 自动负载均衡
    └─ Docker内部DNS轮询

推荐配置:
├─ 使用网络模式: 不映射端口
├─ 使用负载均衡: Nginx/HAProxy
└─ 使用数据卷: 共享存储

2.1.2 自动扩展配置

Compose文件配置:

version: '3.8'

services:
  web:
    image: nginx:latest
    deploy:
      replicas: 3        # 副本数量
      update_config:
        parallelism: 1   # 并行更新数量
        delay: 10s       # 更新间隔
      restart_policy:
        condition: on-failure
    networks:
      - webnet

  # 负载均衡器
  lb:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - web
    networks:
      - webnet

networks:
  webnet:

Nginx负载均衡配置:

# nginx.conf
events {
    worker_connections 1024;
}

http {
    upstream web_backend {
        # Docker Compose服务发现
        server web:80;
    }

    server {
        listen 80;
        
        location / {
            proxy_pass http://web_backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

2.2 负载均衡

2.2.1 Nginx负载均衡

完整配置:

version: '3.8'

services:
  # Web应用(3个副本)
  webapp:
    image: myapp:latest
    deploy:
      replicas: 3
    networks:
      - appnet
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 10s
      timeout: 5s
      retries: 3

  # Nginx负载均衡
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx-lb.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - webapp
    networks:
      - appnet

networks:
  appnet:

Nginx配置:

# nginx-lb.conf
events {
    worker_connections 1024;
}

http {
    upstream app_backend {
        least_conn;  # 最少连接算法
        server webapp:3000;
    }

    server {
        listen 80;
        
        location / {
            proxy_pass http://app_backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            
            # 健康检查
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
        }
    }
}

2.2.2 HAProxy负载均衡

HAProxy配置:

version: '3.8'

services:
  # Web应用
  webapp:
    image: myapp:latest
    deploy:
      replicas: 3
    networks:
      - appnet

  # HAProxy负载均衡
  haproxy:
    image: haproxy:alpine
    ports:
      - "80:80"
      - "8404:8404"  # 管理界面
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    depends_on:
      - webapp
    networks:
      - appnet

networks:
  appnet:

HAProxy配置文件:

# haproxy.cfg
global
    daemon
    maxconn 256

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend http_front
    bind *:80
    default_backend http_back

backend http_back
    balance roundrobin
    option httpchk GET /health
    server webapp1 webapp:3000 check

# 管理界面
listen stats
    bind *:8404
    stats enable
    stats uri /
    stats refresh 10s

三、配置管理

3.1 Config配置

3.1.1 Config基本使用

创建配置:

version: '3.8'

services:
  web:
    image: nginx:latest
    configs:
      - source: nginx_config
        target: /etc/nginx/nginx.conf
    ports:
      - "80:80"

configs:
  nginx_config:
    file: ./nginx.conf

Config说明:

Config特点:
├─ 存储非敏感配置
├─ 文件或字符串形式
├─ 可在多个服务间共享
├─ 支持版本管理
└─ 需要Swarm模式

Config配置:
├─ source: 配置名称
├─ target: 容器内路径
├─ uid/gid: 文件所有者
└─ mode: 文件权限

使用场景:
├─ 配置文件
├─ 环境配置
└─ 应用配置

3.1.2 多配置管理

多配置示例:

version: '3.8'

services:
  app:
    image: myapp:latest
    configs:
      - source: app_config
        target: /app/config.yml
      - source: nginx_config
        target: /etc/nginx/nginx.conf
    environment:
      - CONFIG_PATH=/app/config.yml

configs:
  app_config:
    file: ./config/app.yml
  nginx_config:
    file: ./config/nginx.conf

3.2 Secret密钥管理

3.2.1 Secret基本使用

创建密钥:

version: '3.8'

services:
  db:
    image: mysql:5.7
    secrets:
      - db_password
      - db_root_password
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
      MYSQL_PASSWORD_FILE: /run/secrets/db_password

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

Secret说明:

Secret特点:
├─ 存储敏感信息
├─ 加密存储
├─ 挂载到/run/secrets/
├─ 支持版本管理
└─ 需要Swarm模式

Secret配置:
├─ source: 密钥名称
├─ target: 容器内文件名
├─ uid/gid: 文件所有者
└─ mode: 文件权限(默认0444)

使用场景:
├─ 数据库密码
├─ API密钥
├─ 证书文件
└─ SSH密钥

3.2.2 完整示例

应用密钥管理:

version: '3.8'

services:
  app:
    image: myapp:latest
    secrets:
      - source: db_password
        target: db_password
        mode: 0400
      - source: api_key
        target: api_key
    environment:
      - DB_PASSWORD_FILE=/run/secrets/db_password
      - API_KEY_FILE=/run/secrets/api_key
    ports:
      - "3000:3000"

  db:
    image: mysql:5.7
    secrets:
      - db_root_password
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password

secrets:
  db_password:
    file: ./secrets/db_password.txt
  db_root_password:
    file: ./secrets/db_root_password.txt
  api_key:
    file: ./secrets/api_key.txt

四、网络高级配置

4.1 自定义网络

4.1.1 网络驱动配置

网络配置:

version: '3.8'

services:
  app:
    image: myapp:latest
    networks:
      - frontend
      - backend

networks:
  frontend:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.enable_icc: "true"
      com.docker.network.bridge.enable_ip_masquerade: "true"
    ipam:
      driver: default
      config:
        - subnet: 172.20.0.0/16
          gateway: 172.20.0.1
  
  backend:
    driver: bridge
    internal: true  # 禁止外部访问
    ipam:
      config:
        - subnet: 172.21.0.0/16

网络驱动说明:

网络驱动:
├─ bridge: 桥接网络(默认)
│   ├─ 单主机网络
│   └─ 容器间通信
│
├─ overlay: 覆盖网络
│   ├─ 跨主机网络
│   └─ 需要Swarm模式
│
├─ macvlan: MAC地址VLAN
│   ├─ 容器有独立MAC
│   └─ 直接连接物理网络
│
└─ host: 主机网络
    ├─ 共享主机网络
    └─ 性能最优

网络选项:
├─ internal: 禁止外部访问
├─ enable_ipv6: 启用IPv6
├─ driver_opts: 驱动选项
└─ ipam: IP地址管理

4.1.2 网络隔离

网络隔离示例:

version: '3.8'

services:
  # 前端服务
  frontend:
    image: nginx:latest
    networks:
      - frontend
    ports:
      - "80:80"

  # 后端服务
  backend:
    image: myapp:latest
    networks:
      - frontend
      - backend

  # 数据库服务
  db:
    image: mysql:5.7
    networks:
      - backend
    # 只能被backend访问,不能被frontend访问

  # 缓存服务
  redis:
    image: redis:alpine
    networks:
      - backend

networks:
  frontend:
    # 前端网络,可被外部访问
  backend:
    internal: true
    # 后端网络,禁止外部访问

4.2 服务发现

4.2.1 DNS配置

自定义DNS:

version: '3.8'

services:
  app:
    image: myapp:latest
    dns:
      - 8.8.8.8
      - 8.8.4.4
    dns_search:
      - example.com
    dns_opt:
      - use-vc
      - no-tld-query

服务发现说明:

Docker服务发现:
├─ 自动DNS解析
│   ├─ 服务名作为主机名
│   └─ 容器间通过服务名访问
│
├─ DNS轮询
│   ├─ 多个副本自动轮询
│   └─ 负载均衡
│
└─ 网络别名
    ├─ 多个别名
    └─ 方便服务访问

服务名解析:
├─ 服务名: web
├─ 完整名: web.myproject_default
└─ 别名: 自定义别名

4.2.2 网络别名

别名配置:

version: '3.8'

services:
  app:
    image: myapp:latest
    networks:
      frontend:
        aliases:
          - api
          - backend
      backend:
        aliases:
          - app-server

networks:
  frontend:
  backend:

五、多环境部署

5.1 多配置文件

5.1.1 配置文件继承

基础配置:

# docker-compose.yml
version: '3.8'

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
  
  app:
    image: myapp:latest
    ports:
      - "3000:3000"
  
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root123

开发环境覆盖:

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

services:
  web:
    volumes:
      - ./html:/usr/share/nginx/html
  
  app:
    build: .
    volumes:
      - .:/app
    environment:
      - NODE_ENV=development
      - DEBUG=true
  
  db:
    ports:
      - "3306:3306"

生产环境覆盖:

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

services:
  web:
    restart: always
  
  app:
    image: myregistry.com/myapp:latest
    restart: always
    environment:
      - NODE_ENV=production
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '1'
          memory: 1G
  
  db:
    restart: always
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

使用方法:

# 开发环境(自动加载docker-compose.override.yml)
docker compose up -d

# 生产环境
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# 测试环境
docker compose -f docker-compose.yml -f docker-compose.test.yml up -d

5.2 环境变量管理

5.2.1 多环境变量文件

环境变量文件:

# .env.development
APP_ENV=development
DEBUG=true
DB_HOST=localhost
DB_PORT=3306

# .env.production
APP_ENV=production
DEBUG=false
DB_HOST=db
DB_PORT=3306

# .env.test
APP_ENV=test
DEBUG=true
DB_HOST=test-db
DB_PORT=3306

使用方法:

# 开发环境
docker compose --env-file .env.development up -d

# 生产环境
docker compose --env-file .env.production up -d

# 测试环境
docker compose --env-file .env.test up -d

5.2.2 环境变量替换

配置文件:

version: '3.8'

services:
  app:
    image: myapp:${APP_VERSION:-latest}
    environment:
      - APP_ENV=${APP_ENV}
      - DEBUG=${DEBUG:-false}
    ports:
      - "${APP_PORT:-3000}:3000"
  
  db:
    image: mysql:${DB_VERSION:-5.7}
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}

变量替换规则:

环境变量替换:
├─ ${VAR}: 使用变量值
├─ ${VAR:-default}: 使用默认值
├─ ${VAR:?error}: 变量未设置时报错
└─ ${VAR:+value}: 变量设置时使用value

示例:
├─ ${APP_VERSION:-latest}
│   └─ APP_VERSION未设置时使用latest
│
├─ ${DB_PASSWORD:?DB_PASSWORD is required}
│   └─ DB_PASSWORD未设置时报错
│
└─ ${DEBUG:+true}
    └─ DEBUG设置时使用true

六、本章小结

6.1 高级特性总结

6.1.1 核心特性

资源管理:
├─ CPU限制: cpus
├─ 内存限制: memory
├─ 资源预留: reservations
└─ 重启策略: restart_policy

健康检查:
├─ 检查命令: test
├─ 检查间隔: interval
├─ 超时时间: timeout
└─ 重试次数: retries

日志管理:
├─ 日志驱动: driver
├─ 日志轮转: max-size, max-file
└─ 日志标签: tag

服务扩展:
├─ 副本数量: replicas
├─ 负载均衡: Nginx/HAProxy
└─ 服务发现: DNS

6.1.2 配置管理

Config配置:
├─ 非敏感配置
├─ 文件挂载
├─ 多服务共享
└─ 版本管理

Secret密钥:
├─ 敏感信息
├─ 加密存储
├─ 安全挂载
└─ 权限控制

网络配置:
├─ 自定义网络
├─ 网络隔离
├─ DNS配置
└─ 网络别名

6.2 最佳实践

6.2.1 生产环境建议

资源配置:
✅ 设置合理的资源限制
✅ 配置健康检查
✅ 设置重启策略
✅ 配置日志轮转

安全配置:
✅ 使用Secret管理密钥
✅ 使用网络隔离
✅ 限制容器权限
✅ 定期更新镜像

高可用配置:
✅ 多副本部署
✅ 负载均衡
✅ 健康检查
✅ 自动重启

6.2.2 运维建议

监控告警:
✅ 监控服务状态
✅ 监控资源使用
✅ 监控日志
✅ 设置告警

备份恢复:
✅ 定期备份数据卷
✅ 备份配置文件
✅ 测试恢复流程
✅ 文档化流程

更新维护:
✅ 定期更新镜像
✅ 测试更新流程
✅ 回滚方案
✅ 灰度发布

6.3 下一章预告

下一章: Docker私有仓库

将学习:

  • 🏗️ Registry搭建
  • 🔐 仓库安全配置
  • 📦 镜像管理
  • 🔄 镜像同步

📝 练习题

基础题

  1. 资源限制: 创建一个服务,配置CPU限制为0.5核,内存限制为512M,并验证限制是否生效。

  2. 健康检查: 为一个Web服务配置健康检查,每10秒检查一次,超时时间为5秒,重试3次。

  3. 日志配置: 配置服务的日志轮转,单个日志文件最大10M,最多保留3个文件。

进阶题

  1. 服务扩展: 创建一个包含3个Web应用副本的服务,使用Nginx作为负载均衡器,实现负载均衡。

  2. 网络隔离: 创建一个三层架构应用,配置网络隔离,前端只能访问后端,后端只能访问数据库。

  3. 多环境部署: 为一个应用配置开发、测试、生产三个环境的部署配置,使用不同的配置文件和环境变量。

实践题

  1. 完整微服务部署: 为一个微服务应用设计完整的部署方案,要求:

    • 多服务编排
    • 资源限制
    • 健康检查
    • 日志管理
    • 负载均衡
    • 网络隔离
    • 配置管理
    • 密钥管理
  2. 生产环境配置: 为一个生产环境设计完整的Docker Compose配置,要求:

    • 高可用部署
    • 自动扩展
    • 监控告警
    • 日志收集
    • 数据备份
    • 安全配置