Zerlaer's Notebook

欢迎来到我的博客|

Docker Compose 多容器应用管理实战

Docker Compose 概述

什么是 Docker Compose?

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过一个 YAML 文件,我们可以配置应用程序的服务、网络、卷等,然后使用单个命令来创建和启动所有服务。

Docker Compose 的优势

  • 简化配置:使用 YAML 文件统一配置所有服务
  • 一键部署:通过单个命令启动整个应用栈
  • 环境一致性:确保开发、测试和生产环境的一致性
  • 服务依赖管理:自动处理服务间的依赖关系
  • 扩展性:方便地扩展或缩服务实例

Docker Compose 安装

在 Linux 系统上安装

# 下载最新版本的 Docker Compose
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 添加执行权限
chmod +x /usr/local/bin/docker-compose

# 验证安装
docker-compose --version

在 Windows 和 macOS 上安装

Docker Desktop for Windows 和 macOS 已经内置了 Docker Compose,安装 Docker Desktop 即可使用。

Docker Compose 核心概念

docker-compose.yml 文件结构

version: '3.8'
services:
  service1:
    # 服务配置
  service2:
    # 服务配置
networks:
  # 网络配置
volumes:
  # 卷配置

主要配置选项

  • image:指定服务使用的镜像
  • build:指定构建镜像的 Dockerfile 路径
  • ports:端口映射
  • volumes:数据卷挂载
  • environment:环境变量
  • depends_on:服务依赖关系
  • networks:网络配置
  • restart:重启策略
  • command:覆盖容器的默认命令

基础实战:部署 WordPress 应用

步骤 1:创建 docker-compose.yml 文件

version: '3.8'

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - wordpress_data:/var/www/html
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress

volumes:
  db_data:
  wordpress_data:

步骤 2:启动服务

# 启动服务(后台运行)
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看服务日志
docker-compose logs

# 查看特定服务的日志
docker-compose logs wordpress

步骤 3:访问应用

在浏览器中访问 http://localhost:8000,即可看到 WordPress 安装页面。

步骤 4:停止和清理

# 停止服务
docker-compose stop

# 启动服务
docker-compose start

# 重启服务
docker-compose restart

# 停止并删除容器、网络和卷
docker-compose down -v

进阶实战:部署完整的微服务架构

示例:电商系统微服务架构

version: '3.8'

services:
  # 前端服务
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    depends_on:
      - api
    environment:
      - API_URL=http://api:8000

  # API 网关
  api:
    build: ./api
    ports:
      - "8000:8000"
    depends_on:
      - product-service
      - order-service
      - user-service
    environment:
      - PRODUCT_SERVICE_URL=http://product-service:8001
      - ORDER_SERVICE_URL=http://order-service:8002
      - USER_SERVICE_URL=http://user-service:8003

  # 产品服务
  product-service:
    build: ./product-service
    depends_on:
      - product-db
    environment:
      - DB_HOST=product-db
      - DB_PORT=5432
      - DB_NAME=product
      - DB_USER=postgres
      - DB_PASSWORD=secret

  # 订单服务
  order-service:
    build: ./order-service
    depends_on:
      - order-db
    environment:
      - DB_HOST=order-db
      - DB_PORT=5432
      - DB_NAME=order
      - DB_USER=postgres
      - DB_PASSWORD=secret

  # 用户服务
  user-service:
    build: ./user-service
    depends_on:
      - user-db
    environment:
      - DB_HOST=user-db
      - DB_PORT=5432
      - DB_NAME=user
      - DB_USER=postgres
      - DB_PASSWORD=secret

  # 数据库服务
  product-db:
    image: postgres:13
    volumes:
      - product-db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=product
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secret

  order-db:
    image: postgres:13
    volumes:
      - order-db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=order
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secret

  user-db:
    image: postgres:13
    volumes:
      - user-db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=user
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secret

  # 消息队列
  rabbitmq:
    image: rabbitmq:3-management
    ports:
      - "5672:5672"
      - "15672:15672"
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq

  # 缓存
  redis:
    image: redis:6
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data

# 网络配置
networks:
  default:
    name: ecommerce-network

# 卷配置
volumes:
  product-db-data:
  order-db-data:
  user-db-data:
  rabbitmq-data:
  redis-data:

部署和管理

# 构建并启动所有服务
docker-compose up -d --build

# 查看服务状态
docker-compose ps

# 扩展服务实例(例如,将产品服务扩展到 3 个实例)
docker-compose up -d --scale product-service=3

# 查看服务日志(跟踪模式)
docker-compose logs -f

# 进入特定服务容器
docker-compose exec api bash

# 执行服务健康检查
docker-compose exec product-service curl -s http://localhost:8001/health

高级配置技巧

1. 使用环境变量文件

创建 .env 文件:

# 数据库配置
DB_HOST=db
DB_PORT=5432
DB_NAME=app
DB_USER=postgres
DB_PASSWORD=secret

# 应用配置
APP_ENV=production
APP_DEBUG=false

在 docker-compose.yml 中使用:

services:
  app:
    image: my-app
    environment:
      - DB_HOST=${DB_HOST}
      - DB_PORT=${DB_PORT}
      - DB_NAME=${DB_NAME}
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}
      - APP_ENV=${APP_ENV}
      - APP_DEBUG=${APP_DEBUG}

2. 使用 extends 指令复用配置

创建 common.yml 文件:

services:
  base-service:
    image: node:14-alpine
    restart: always
    environment:
      - NODE_ENV=production
    volumes:
      - .:/app
    working_dir: /app

在 docker-compose.yml 中使用:

extends:
  file: common.yml
  service: base-service

services:
  api:
    extends:
      file: common.yml
      service: base-service
    ports:
      - "8000:8000"
    command: npm run start:api

  worker:
    extends:
      file: common.yml
      service: base-service
    command: npm run start:worker

3. 多环境配置

创建 docker-compose.override.yml 文件,用于开发环境覆盖默认配置:

services:
  app:
    environment:
      - APP_ENV=development
      - APP_DEBUG=true
    volumes:
      - .:/app
      - /app/node_modules
    ports:
      - "3000:3000"
    command: npm run dev

Docker Compose 会自动加载 docker-compose.override.yml 文件,覆盖默认配置。

4. 健康检查配置

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

  db:
    image: postgres:13
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 30s
      timeout: 10s
      retries: 3

监控与日志管理

1. 集中式日志管理

services:
  # 应用服务
  app:
    image: my-app
    logging:
      driver: "fluentd"
      options:
        fluentd-address: localhost:24224
        tag: app.{{.Name}}

  # Fluentd 服务
  fluentd:
    image: fluent/fluentd:v1.14-debian
    volumes:
      - ./fluentd/conf:/fluentd/etc
      - fluentd-data:/fluentd/log
    ports:
      - "24224:24224"

  # Elasticsearch 服务
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0
    environment:
      - discovery.type=single-node
    volumes:
      - es-data:/usr/share/elasticsearch/data

  # Kibana 服务
  kibana:
    image: docker.elastic.co/kibana/kibana:7.14.0
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch

volumes:
  fluentd-data:
  es-data:

2. 服务监控

services:
  # 应用服务
  app:
    image: my-app
    ports:
      - "3000:3000"

  # Prometheus 服务
  prometheus:
    image: prom/prometheus:v2.28.0
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  # Grafana 服务
  grafana:
    image: grafana/grafana:8.1.0
    volumes:
      - grafana-data:/var/lib/grafana
    ports:
      - "3001:3000"
    depends_on:
      - prometheus

volumes:
  grafana-data:

常见问题与解决方案

1. 服务启动顺序问题

问题:依赖服务尚未就绪,导致服务启动失败。

解决方案

  • 使用 depends_on 定义服务依赖关系
  • 实现服务启动重试机制
  • 使用健康检查确保依赖服务就绪

2. 资源限制问题

问题:服务使用过多资源,导致系统性能下降。

解决方案

  • 为服务设置资源限制:
services:
  app:
    image: my-app
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

3. 网络连接问题

问题:服务间网络连接不稳定。

解决方案

  • 为服务指定固定的网络别名
  • 实现网络连接重试机制
  • 使用 Docker 网络的内置 DNS 服务

4. 数据持久化问题

问题:容器重启后数据丢失。

解决方案

  • 使用命名卷进行数据持久化
  • 配置适当的卷备份策略
  • 考虑使用外部存储服务

最佳实践

1. 配置管理

  • 使用环境变量文件管理配置:.env 文件
  • 为不同环境创建不同的配置文件:docker-compose.prod.ymldocker-compose.dev.yml
  • 避免在配置文件中硬编码敏感信息,使用 Docker secrets 或环境变量

2. 镜像管理

  • 使用多阶段构建减少镜像大小
  • 为镜像添加合理的标签,避免使用 latest 标签
  • 定期清理未使用的镜像和容器

3. 服务设计

  • 每个服务只负责一个功能,遵循单一职责原则
  • 服务间通过网络协议通信,避免共享文件系统
  • 为服务实现健康检查和优雅启动/关闭机制

4. 部署策略

  • 使用 CI/CD 管道自动化部署流程
  • 实现蓝绿部署或滚动更新,减少服务 downtime
  • 定期备份关键数据和配置

5. 监控与维护

  • 实现集中式日志管理,便于问题排查
  • 配置服务监控,及时发现性能瓶颈和故障
  • 建立完善的告警机制,确保服务可靠性

总结

Docker Compose 是一个强大的工具,它简化了多容器应用的管理和部署。通过本文的学习,你应该已经掌握了 Docker Compose 的基础用法、进阶技巧和最佳实践,能够使用它来部署从简单应用到复杂微服务架构的各种场景。

作为一名运维工程师,掌握 Docker Compose 技术可以大大提高工作效率,实现应用的快速部署和管理。在实际工作中,我们需要根据具体的应用场景和需求,灵活运用 Docker Compose 的各种功能,不断优化配置,才能真正发挥其最大价值。

参考资料