多容器应用编排 #

应用架构设计 #

典型Web应用架构 #

text
┌─────────────────────────────────────────────────────┐
│                   Web应用架构                        │
├─────────────────────────────────────────────────────┤
│                                                     │
│  ┌─────────┐                                        │
│  │   CDN   │                                        │
│  └────┬────┘                                        │
│       │                                             │
│  ┌────▼────┐     ┌─────────┐                        │
│  │   Nginx │────→│  App    │                        │
│  │(反向代理)│     │(Node.js)│                        │
│  └─────────┘     └────┬────┘                        │
│                       │                             │
│       ┌───────────────┼───────────────┐             │
│       │               │               │             │
│  ┌────▼────┐     ┌────▼────┐    ┌────▼────┐        │
│  │  MySQL  │     │  Redis  │    │  MQ     │        │
│  │(主数据库)│     │ (缓存)  │    │(消息队列)│        │
│  └─────────┘     └─────────┘    └─────────┘        │
│                                                     │
└─────────────────────────────────────────────────────┘

基础编排示例 #

简单Web应用 #

yaml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html
    depends_on:
      - app

  app:
    image: node:18-alpine
    working_dir: /app
    volumes:
      - ./app:/app
    command: npm start
    environment:
      - NODE_ENV=production
    depends_on:
      - db
      - redis

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydb
    volumes:
      - mysql-data:/var/lib/mysql

  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data

volumes:
  mysql-data:
  redis-data:

服务发现与通信 #

网络配置 #

yaml
version: '3.8'

services:
  web:
    image: nginx:alpine
    networks:
      - frontend
    ports:
      - "80:80"

  app:
    image: myapp
    networks:
      - frontend
      - backend
    environment:
      - DB_HOST=db
      - REDIS_HOST=redis

  db:
    image: mysql:8.0
    networks:
      - backend

  redis:
    image: redis:alpine
    networks:
      - backend

networks:
  frontend:
  backend:
    internal: true

服务依赖 #

yaml
version: '3.8'

services:
  app:
    image: myapp
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

  db:
    image: mysql:8.0
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

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

负载均衡 #

Nginx负载均衡 #

yaml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - app1
      - app2
      - app3

  app1:
    image: myapp
    environment:
      - INSTANCE_ID=1
    networks:
      - app-network

  app2:
    image: myapp
    environment:
      - INSTANCE_ID=2
    networks:
      - app-network

  app3:
    image: myapp
    environment:
      - INSTANCE_ID=3
    networks:
      - app-network

networks:
  app-network:

nginx.conf #

nginx
upstream backend {
    server app1:3000;
    server app2:3000;
    server app3:3000;
}

server {
    listen 80;
    
    location / {
        proxy_pass http://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;
    }
}

使用scale扩展 #

bash
# 启动服务
docker-compose up -d

# 扩展app服务到5个实例
docker-compose up -d --scale app=5

# nginx配置需要使用动态发现
# 或使用Docker Swarm模式

数据库主从复制 #

MySQL主从配置 #

yaml
version: '3.8'

services:
  mysql-master:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydb
      MYSQL_REPLICATION_MODE: master
      MYSQL_REPLICATION_USER: repl
      MYSQL_REPLICATION_PASSWORD: repl
    volumes:
      - mysql-master-data:/var/lib/mysql
      - ./master.cnf:/etc/mysql/conf.d/master.cnf
    networks:
      - db-network

  mysql-slave:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_REPLICATION_MODE: slave
      MYSQL_REPLICATION_USER: repl
      MYSQL_REPLICATION_PASSWORD: repl
      MYSQL_MASTER_HOST: mysql-master
      MYSQL_MASTER_PORT: 3306
    volumes:
      - mysql-slave-data:/var/lib/mysql
      - ./slave.cnf:/etc/mysql/conf.d/slave.cnf
    depends_on:
      - mysql-master
    networks:
      - db-network

volumes:
  mysql-master-data:
  mysql-slave-data:

networks:
  db-network:

master.cnf #

ini
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW

slave.cnf #

ini
[mysqld]
server-id = 2
relay-log = relay-bin
read_only = 1

Redis集群 #

Redis Sentinel #

yaml
version: '3.8'

services:
  redis-master:
    image: redis:alpine
    command: redis-server
    networks:
      - redis-network

  redis-slave:
    image: redis:alpine
    command: redis-server --slaveof redis-master 6379
    depends_on:
      - redis-master
    networks:
      - redis-network

  sentinel:
    image: redis:alpine
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel.conf:/etc/redis/sentinel.conf
    depends_on:
      - redis-master
    networks:
      - redis-network

networks:
  redis-network:

sentinel.conf #

ini
sentinel monitor mymaster redis-master 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

消息队列集成 #

RabbitMQ #

yaml
version: '3.8'

services:
  rabbitmq:
    image: rabbitmq:3-management-alpine
    ports:
      - "5672:5672"
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: admin
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    networks:
      - app-network

  producer:
    image: myapp-producer
    environment:
      - RABBITMQ_HOST=rabbitmq
    depends_on:
      - rabbitmq
    networks:
      - app-network

  consumer:
    image: myapp-consumer
    environment:
      - RABBITMQ_HOST=rabbitmq
    depends_on:
      - rabbitmq
    networks:
      - app-network
    deploy:
      replicas: 3

volumes:
  rabbitmq-data:

networks:
  app-network:

完整应用示例 #

电商应用 #

yaml
version: '3.8'

services:
  # 前端网关
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    networks:
      - frontend
    depends_on:
      - frontend
      - api

  # 前端应用
  frontend:
    image: myapp-frontend
    networks:
      - frontend
    environment:
      - API_URL=http://api:8000

  # API网关
  api:
    image: myapp-api
    networks:
      - frontend
      - backend
    environment:
      - USER_SERVICE=http://user-service:8001
      - PRODUCT_SERVICE=http://product-service:8002
      - ORDER_SERVICE=http://order-service:8003
    depends_on:
      - user-service
      - product-service
      - order-service

  # 用户服务
  user-service:
    image: myapp-user-service
    networks:
      - backend
    environment:
      - DB_HOST=user-db
      - REDIS_HOST=redis
    depends_on:
      - user-db
      - redis

  # 商品服务
  product-service:
    image: myapp-product-service
    networks:
      - backend
    environment:
      - DB_HOST=product-db
      - REDIS_HOST=redis
    depends_on:
      - product-db
      - redis

  # 订单服务
  order-service:
    image: myapp-order-service
    networks:
      - backend
    environment:
      - DB_HOST=order-db
      - REDIS_HOST=redis
      - MQ_HOST=rabbitmq
    depends_on:
      - order-db
      - redis
      - rabbitmq

  # 数据库
  user-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: user_db
    volumes:
      - user-db-data:/var/lib/mysql
    networks:
      - backend

  product-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: product_db
    volumes:
      - product-db-data:/var/lib/mysql
    networks:
      - backend

  order-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: order_db
    volumes:
      - order-db-data:/var/lib/mysql
    networks:
      - backend

  # 缓存
  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data
    networks:
      - backend

  # 消息队列
  rabbitmq:
    image: rabbitmq:3-management-alpine
    ports:
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: admin
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    networks:
      - backend

volumes:
  user-db-data:
  product-db-data:
  order-db-data:
  redis-data:
  rabbitmq-data:

networks:
  frontend:
  backend:
    internal: true

小结 #

本节学习了多容器应用编排:

  • 应用架构设计
  • 服务发现与通信
  • 负载均衡配置
  • 数据库主从复制
  • Redis集群配置
  • 消息队列集成
  • 完整应用示例

下一步 #

接下来,让我们学习 Compose网络与存储,深入了解Compose中的网络和存储配置。