Docker Compose 完整教程

Docker Compose 是一个用于定义和管理多容器 Docker 应用程序的工具。通过一个 YAML 文件来配置应用程序的服务,然后使用一个命令就可以创建并启动所有服务。

1. Docker Compose 基础概念

1.1 核心概念

  • Service(服务):应用程序的一个组件,如数据库、Web服务器等
  • Project(项目):由一组关联的服务组成的完整应用程序
  • Container(容器):服务的运行实例

1.2 主要优势

  • 简化多容器应用的部署和管理
  • 通过代码定义基础设施(Infrastructure as Code)
  • 便于开发、测试和生产环境的一致性
  • 支持服务扩缩容和负载均衡

2. 安装 Docker Compose

2.1 Linux 安装

# 下载最新版本
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
​
# 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
​
# 验证安装
docker-compose --version

2.2 通过 pip 安装

pip install docker-compose

3. Compose 文件结构

**Docker Compose 使用 YAML 文件来定义服务。文件通常命名为 **docker-compose.yml

3.1 基本结构

version: '3.8'  # Compose文件格式版本
​
services:       # 定义服务
  service1:
    # 服务1配置
  service2:
    # 服务2配置
​
volumes:        # 定义数据卷(可选)
  volume1:
​
networks:       # 定义网络(可选)
  network1:
​
configs:        # 定义配置(可选)
  config1:
​
secrets:        # 定义密钥(可选)
  secret1:

4. 服务配置详解

4.1 镜像相关

image - 指定镜像

services:
  web:
    image: nginx:1.21-alpine
  
  app:
    image: my-app:latest
    
  db:
    image: postgres:13

build - 构建镜像

services:
  web:
    build: .  # 使用当前目录的Dockerfile
  
  app:
    build:
      context: ./app        # 构建上下文路径
      dockerfile: Dockerfile.dev  # 指定Dockerfile
      args:                # 构建参数
        - BUILD_ENV=development
        - VERSION=1.0
      target: development  # 多阶段构建目标

4.2 端口映射

ports - 暴露端口

services:
  web:
    image: nginx
    ports:
      - "8080:80"          # 主机端口:容器端口
      - "443:443"
      - "127.0.0.1:8081:80"  # 绑定到特定IP

expose - 内部端口暴露

services:
  app:
    image: my-app
    expose:
      - "3000"  # 只在内部网络中暴露,不映射到主机

4.3 环境变量

environment - 设置环境变量

services:
  db:
    image: postgres:13
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      # 或使用数组形式
      # - POSTGRES_DB=myapp
      # - POSTGRES_USER=user

env_file - 从文件加载环境变量

services:
  app:
    image: my-app
    env_file:
      - .env
      - .env.local

4.4 数据卷

volumes - 挂载数据卷

services:
  web:
    image: nginx
    volumes:
      - ./html:/usr/share/nginx/html:ro  # 主机路径:容器路径:权限
      - nginx-config:/etc/nginx/conf.d   # 命名卷
      - /var/log/nginx                   # 匿名卷
​
volumes:
  nginx-config:  # 定义命名卷

4.5 网络配置

networks - 网络设置

services:
  web:
    image: nginx
    networks:
      - frontend
      - backend
  
  db:
    image: postgres
    networks:
      - backend
​
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 内部网络,不能访问外网

4.6 依赖关系

depends_on - 服务依赖

services:
  web:
    image: nginx
    depends_on:
      - app
      - db
  
  app:
    image: my-app
    depends_on:
      db:
        condition: service_healthy  # 等待健康检查通过
  
  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 30s
      timeout: 10s
      retries: 3

4.7 重启策略

restart - 重启策略

services:
  web:
    image: nginx
    restart: always        # 总是重启
  
  app:
    image: my-app
    restart: unless-stopped  # 除非手动停止
  
  worker:
    image: my-worker
    restart: on-failure     # 失败时重启
  
  temp:
    image: temp-service
    restart: "no"           # 不重启(默认)

4.8 资源限制

deploy - 部署配置

services:
  web:
    image: nginx
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
      replicas: 3
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3

4.9 健康检查

healthcheck - 健康检查

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

4.10 其他常用字段

services:
  app:
    image: my-app
    container_name: my-app-container  # 自定义容器名
    hostname: app-server             # 容器主机名
    user: 1000:1000                 # 运行用户
    working_dir: /app               # 工作目录
    command: ["python", "app.py"]   # 覆盖默认命令
    entrypoint: ["/entrypoint.sh"]  # 覆盖入口点
    stdin_open: true                # 等同于 docker run -i
    tty: true                       # 等同于 docker run -t
    privileged: true                # 特权模式
    cap_add:                        # 添加Linux能力
      - SYS_ADMIN
    cap_drop:                       # 移除Linux能力
      - NET_ADMIN
    devices:                        # 设备映射
      - "/dev/sda:/dev/sda"
    dns:                           # DNS服务器
      - 8.8.8.8
      - 8.8.4.4
    extra_hosts:                   # 额外的主机映射
      - "api.example.com:192.168.1.100"
    logging:                       # 日志配置
      driver: json-file
      options:
        max-size: "200k"
        max-file: "10"

5. 实战示例

5.1 简单 Web 应用示例

项目结构:

webapp/
├── docker-compose.yml
├── .env
├── nginx/
│   └── nginx.conf
├── app/
│   ├── Dockerfile
│   ├── app.py
│   └── requirements.txt
└── data/

docker-compose.yml:

version: '3.8'
​
services:
  # Nginx 反向代理
  nginx:
    image: nginx:1.21-alpine
    container_name: webapp-nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    depends_on:
      - app
    networks:
      - frontend
    restart: unless-stopped
​
  # Python Web 应用
  app:
    build:
      context: ./app
      dockerfile: Dockerfile
    container_name: webapp-app
    environment:
      - FLASK_ENV=production
      - DATABASE_URL=postgresql://user:password@db:5432/webapp
    volumes:
      - ./app:/app
      - app-logs:/app/logs
    depends_on:
      db:
        condition: service_healthy
    networks:
      - frontend
      - backend
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
​
  # PostgreSQL 数据库
  db:
    image: postgres:13-alpine
    container_name: webapp-db
    environment:
      POSTGRES_DB: webapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - backend
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d webapp"]
      interval: 30s
      timeout: 5s
      retries: 5
​
  # Redis 缓存
  redis:
    image: redis:6-alpine
    container_name: webapp-redis
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - backend
    restart: unless-stopped
​
  # 后台任务处理器
  worker:
    build:
      context: ./app
      dockerfile: Dockerfile
    container_name: webapp-worker
    command: celery -A app.celery worker --loglevel=info
    environment:
      - CELERY_BROKER_URL=redis://redis:6379/0
      - DATABASE_URL=postgresql://user:password@db:5432/webapp
    volumes:
      - ./app:/app
      - worker-logs:/app/logs
    depends_on:
      - redis
      - db
    networks:
      - backend
    restart: unless-stopped
​
volumes:
  postgres-data:
  redis-data:
  app-logs:
  worker-logs:
​
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

.env 文件:

# 数据库配置
POSTGRES_DB=webapp
POSTGRES_USER=user
POSTGRES_PASSWORD=your_secure_password
​
# 应用配置
FLASK_ENV=production
SECRET_KEY=your_secret_key
​
# Redis配置
REDIS_URL=redis://redis:6379/0

5.2 微服务架构示例

version: '3.8'
​
services:
  # API Gateway
  gateway:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./gateway/nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - user-service
      - product-service
      - order-service
    networks:
      - public
​
  # 用户服务
  user-service:
    build: ./services/user-service
    environment:
      - DATABASE_URL=postgresql://user:pass@user-db:5432/users
      - JWT_SECRET=user_jwt_secret
    depends_on:
      - user-db
    networks:
      - public
      - user-network
    deploy:
      replicas: 2
​
  user-db:
    image: postgres:13
    environment:
      POSTGRES_DB: users
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - user-db-data:/var/lib/postgresql/data
    networks:
      - user-network
​
  # 商品服务
  product-service:
    build: ./services/product-service
    environment:
      - MONGO_URL=mongodb://product-db:27017/products
    depends_on:
      - product-db
    networks:
      - public
      - product-network
    deploy:
      replicas: 2
​
  product-db:
    image: mongo:4.4
    volumes:
      - product-db-data:/data/db
    networks:
      - product-network
​
  # 订单服务
  order-service:
    build: ./services/order-service
    environment:
      - DATABASE_URL=postgresql://user:pass@order-db:5432/orders
      - USER_SERVICE_URL=http://user-service:3000
      - PRODUCT_SERVICE_URL=http://product-service:3000
    depends_on:
      - order-db
    networks:
      - public
      - order-network
​
  order-db:
    image: postgres:13
    environment:
      POSTGRES_DB: orders
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - order-db-data:/var/lib/postgresql/data
    networks:
      - order-network
​
  # 消息队列
  rabbitmq:
    image: rabbitmq:3-management
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: admin
    ports:
      - "15672:15672"  # 管理界面
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    networks:
      - message-queue
​
  # 监控服务
  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    networks:
      - monitoring
​
  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana-data:/var/lib/grafana
    depends_on:
      - prometheus
    networks:
      - monitoring
​
volumes:
  user-db-data:
  product-db-data:
  order-db-data:
  rabbitmq-data:
  prometheus-data:
  grafana-data:
​
networks:
  public:
    driver: bridge
  user-network:
    driver: bridge
    internal: true
  product-network:
    driver: bridge
    internal: true
  order-network:
    driver: bridge
    internal: true
  message-queue:
    driver: bridge
  monitoring:
    driver: bridge

5.3 开发环境示例

version: '3.8'
​
services:
  # 开发用Web服务器
  web:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - .:/app                    # 代码热重载
      - /app/node_modules         # 避免覆盖node_modules
    environment:
      - NODE_ENV=development
      - CHOKIDAR_USEPOLLING=true  # 支持文件监听
    depends_on:
      - db
      - redis
    networks:
      - dev-network
​
  # 数据库(开发用)
  db:
    image: postgres:13
    environment:
      POSTGRES_DB: app_dev
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: dev
    ports:
      - "5432:5432"  # 暴露端口便于调试
    volumes:
      - dev-db-data:/var/lib/postgresql/data
      - ./db/seeds:/docker-entrypoint-initdb.d  # 测试数据
    networks:
      - dev-network
​
  # Redis(开发用)
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    networks:
      - dev-network
​
  # 邮件测试服务
  mailhog:
    image: mailhog/mailhog
    ports:
      - "1025:1025"  # SMTP
      - "8025:8025"  # Web UI
    networks:
      - dev-network
​
  # 文件同步服务(可选)
  sync:
    image: alpine
    command: >
      sh -c "apk add --no-cache inotify-tools &&
             while inotifywait -r -e modify,create,delete,move /app; do
               echo 'Files changed'
             done"
    volumes:
      - .:/app
    networks:
      - dev-network
​
volumes:
  dev-db-data:
​
networks:
  dev-network:
    driver: bridge

6. 高级功能

6.1 多环境配置

基础配置 docker-compose.yml:

version: '3.8'
​
services:
  web:
    image: my-app:latest
    ports:
      - "80:80"
  
  db:
    image: postgres:13
    environment:
      POSTGRES_DB: myapp

开发环境覆盖 docker-compose.override.yml:

services:
  web:
    build: .
    volumes:
      - .:/app
    environment:
      - DEBUG=true
    
  db:
    ports:
      - "5432:5432"

生产环境覆盖 docker-compose.prod.yml:

services:
  web:
    deploy:
      replicas: 3
      resources:
        limits:
          memory: 512M
    restart: always
    
  db:
    volumes:
      - db-data:/var/lib/postgresql/data
    restart: always
​
volumes:
  db-data:

6.2 配置和密钥管理

version: '3.8'
​
services:
  web:
    image: nginx
    configs:
      - source: nginx-config
        target: /etc/nginx/nginx.conf
    secrets:
      - ssl-cert
      - ssl-key
​
configs:
  nginx-config:
    file: ./nginx.conf
​
secrets:
  ssl-cert:
    file: ./ssl/cert.pem
  ssl-key:
    file: ./ssl/key.pem

6.3 扩展和include

docker-compose.yml:

version: '3.8'
​
include:
  - docker-compose.base.yml
  - docker-compose.monitoring.yml
​
services:
  app:
    extends:
      file: docker-compose.base.yml
      service: base-app
    environment:
      - NODE_ENV=production

7. 常用命令

7.1 基础命令

# 启动服务
docker-compose up                    # 启动所有服务
docker-compose up -d                 # 后台启动
docker-compose up web db             # 启动指定服务
​
# 停止服务
docker-compose down                  # 停止并删除容器
docker-compose down -v               # 同时删除数据卷
docker-compose stop                  # 仅停止容器
​
# 查看状态
docker-compose ps                    # 查看服务状态
docker-compose logs                  # 查看日志
docker-compose logs -f web           # 实时查看指定服务日志
​
# 执行命令
docker-compose exec web bash        # 进入容器
docker-compose run web python manage.py migrate  # 运行一次性命令

7.2 管理命令

# 构建镜像
docker-compose build                 # 构建所有服务
docker-compose build --no-cache web  # 强制重新构建
​
# 拉取镜像
docker-compose pull                  # 拉取所有镜像
​
# 扩缩容
docker-compose up -d --scale web=3   # 扩展web服务到3个实例
​
# 重启服务
docker-compose restart              # 重启所有服务
docker-compose restart web          # 重启指定服务
​
# 配置验证
docker-compose config               # 验证并显示配置
docker-compose config --services   # 列出所有服务名

7.3 多环境命令

# 使用不同的compose文件
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
​
# 使用环境变量文件
docker-compose --env-file .env.prod up -d
​
# 指定项目名
docker-compose -p myproject up -d

8. 最佳实践

8.1 文件组织

project/
├── docker-compose.yml              # 主配置文件
├── docker-compose.override.yml     # 开发环境覆盖
├── docker-compose.prod.yml         # 生产环境配置
├── .env                           # 环境变量
├── .env.example                   # 环境变量示例
├── dockerfiles/                   # Dockerfile目录
│   ├── app/
│   └── nginx/
├── config/                        # 配置文件目录
│   ├── nginx/
│   └── postgres/
└── data/                          # 持久化数据目录

8.2 安全建议

  • **使用 **.env 文件管理敏感信息,不要提交到版本控制
  • 为数据库等服务使用强密码
  • 限制容器的资源使用
  • 使用非root用户运行容器
  • 定期更新基础镜像

8.3 性能优化

  • 使用多阶段构建减小镜像大小
  • 合理设置健康检查间隔
  • 使用适当的重启策略
  • 配置资源限制防止资源耗尽

8.4 开发效率

  • **使用 **docker-compose.override.yml 进行本地开发配置
  • 挂载代码目录实现热重载
  • **使用 **depends_on 和健康检查确保服务启动顺序
  • 合理使用网络隔离

9. 故障排除

9.1 常见问题

# 服务无法启动
docker-compose logs service-name     # 查看服务日志
docker-compose config               # 验证配置文件
​
# 网络连接问题
docker network ls                   # 查看网络
docker-compose exec service ping target  # 测试连通性
​
# 数据卷问题
docker volume ls                    # 查看数据卷
docker-compose down -v              # 删除数据卷重新开始
​
# 端口占用
netstat -tulpn | grep :8080        # 检查端口占用
docker-compose ps                  # 查看端口映射

9.2 调试技巧

  • **使用 **docker-compose config 验证配置
  • **通过 **docker-compose logs -f 实时查看日志
  • **使用 **docker-compose exec 进入容器调试
  • 检查环境变量是否正确传递

10. 总结

Docker Compose 是管理多容器应用的强大工具。通过本教程,你应该能够:

  1. 理解 Docker Compose 的基本概念和文件结构
  2. 掌握各种服务配置选项的使用方法
  3. 编写适用于不同场景的 compose 文件
  4. 使用最佳实践来组织和管理项目
  5. 解决常见的部署和运行问题