Docker Compose教程#

技术介绍#

Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。通过Docker Compose,您可以使用YAML文件来配置应用程序的服务,然后使用单个命令创建和启动所有服务。Docker Compose简化了多容器应用的开发、测试和部署过程。

Docker Compose核心概念#

  • 服务:一个服务对应一个容器,是Docker Compose的基本单位
  • 网络:服务之间的通信网络
  • :服务的持久化存储
  • 环境变量:服务的配置参数
  • 配置文件:定义服务、网络和卷的YAML文件

Docker Compose架构#

  • Docker Compose CLI:命令行工具,用于管理多容器应用
  • Docker Compose文件:YAML格式的配置文件,定义应用的服务、网络和卷
  • Docker Engine:Docker引擎,负责运行容器

入门级使用#

安装Docker Compose#

在不同操作系统上安装Docker Compose:

# Linux
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

# macOS
brew install docker-compose

# Windows
# Docker Desktop for Windows 已经包含了Docker Compose

# 验证安装
docker-compose --version

基本Docker Compose命令#

使用Docker Compose的基本命令:

# 查看Docker Compose版本
docker-compose --version

# 启动服务
docker-compose up

# 后台启动服务
docker-compose up -d

# 停止服务
docker-compose down

# 查看服务状态
docker-compose ps

# 查看服务日志
docker-compose logs

# 构建服务
docker-compose build

# 拉取服务镜像
docker-compose pull

# 重启服务
docker-compose restart

# 停止服务
docker-compose stop

# 启动服务
docker-compose start

基本Docker Compose文件#

创建基本的Docker Compose文件:

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
    restart: always
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: mydb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    volumes:
      - db_data:/var/lib/mysql
    restart: always

volumes:
  db_data:

运行应用:

# 启动应用
docker-compose up -d

# 查看服务状态
docker-compose ps

# 访问应用
curl http://localhost

# 停止应用
docker-compose down

初级使用#

Docker Compose服务配置#

配置Docker Compose服务:

# docker-compose.yml
version: '3'
services:
  web:
    # 使用构建上下文
    build: .
    # 或使用指定的Dockerfile
    # build:
    #   context: .
    #   dockerfile: Dockerfile.dev
    # 镜像名称
    image: myapp:latest
    # 容器名称
    container_name: myapp-web
    # 端口映射
    ports:
      - "8080:80"
    # 环境变量
    environment:
      - DEBUG=1
      - APP_ENV=development
    # 环境变量文件
    env_file:
      - .env
    # 卷挂载
    volumes:
      - .:/app
      - node_modules:/app/node_modules
    # 网络
    networks:
      - mynetwork
    # 依赖关系
    depends_on:
      - db
    # 重启策略
    restart: unless-stopped
    # 资源限制
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

  db:
    image: postgres:12
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - mynetwork

volumes:
  node_modules:
  postgres_data:

networks:
  mynetwork:
    driver: bridge

Docker Compose网络配置#

配置Docker Compose网络:

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    networks:
      - frontend

  api:
    image: node:14
    networks:
      - frontend
      - backend

  db:
    image: mysql:5.7
    networks:
      - backend

networks:
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.18.0.0/16
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.19.0.0/16

Docker Compose卷配置#

配置Docker Compose卷:

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    volumes:
      # 绑定挂载
      - ./html:/usr/share/nginx/html
      # 命名卷
      - static_files:/app/static
      # 临时文件系统
      - type: tmpfs
        target: /tmp

  db:
    image: postgres:12
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  static_files:
  postgres_data:
    driver: local
    driver_opts:
      type: 'none'
      o: 'bind'
      device: '/path/to/postgres/data'

中级使用#

Docker Compose多环境配置#

使用Docker Compose配置多环境:

# docker-compose.yml (基础配置)
version: '3'
services:
  web:
    image: myapp:latest
    ports:
      - "80:80"
    volumes:
      - .:/app
    depends_on:
      - db

  db:
    image: postgres:12
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

# docker-compose.override.yml (开发环境配置)
version: '3'
services:
  web:
    build: .
    environment:
      - DEBUG=1
      - APP_ENV=development

  db:
    environment:
      - POSTGRES_PASSWORD=dev_password

# docker-compose.prod.yml (生产环境配置)
version: '3'
services:
  web:
    image: myapp:latest
    environment:
      - DEBUG=0
      - APP_ENV=production

  db:
    environment:
      - POSTGRES_PASSWORD=prod_password

# 使用开发环境配置
docker-compose up -d

# 使用生产环境配置
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Docker Compose健康检查#

配置Docker Compose健康检查:

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  db:
    image: postgres:12
    environment:
      POSTGRES_PASSWORD: password
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Docker Compose环境变量#

使用Docker Compose环境变量:

# docker-compose.yml
version: '3'
services:
  web:
    image: myapp:latest
    environment:
      - DEBUG=${DEBUG:-0}
      - APP_ENV=${APP_ENV:-development}
      - DATABASE_URL=${DATABASE_URL}
    ports:
      - "${PORT:-8080}:80"

# .env 文件
DEBUG=1
APP_ENV=development
DATABASE_URL=postgres://user:password@db:5432/mydb
PORT=8080

# 使用环境变量启动服务
docker-compose up -d

中上级使用#

Docker Compose构建配置#

配置Docker Compose构建选项:

# docker-compose.yml
version: '3'
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        - NODE_ENV=production
        - BUILD_DATE=${BUILD_DATE}
        - BUILD_VERSION=${BUILD_VERSION}
    image: myapp:${BUILD_VERSION:-latest}
    ports:
      - "80:80"

# Dockerfile
FROM node:14-alpine

ARG NODE_ENV=production
ARG BUILD_DATE
ARG BUILD_VERSION

ENV NODE_ENV=${NODE_ENV}

LABEL org.label-schema.build-date=${BUILD_DATE}
LABEL org.label-schema.version=${BUILD_VERSION}

WORKDIR /app

COPY package*.json ./
RUN npm install --only=production

COPY . .

EXPOSE 80

CMD ["npm", "start"]

# 构建服务
docker-compose build --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") --build-arg BUILD_VERSION=1.0.0

Docker Compose网络高级配置#

配置Docker Compose网络高级选项:

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    networks:
      frontend:
        aliases:
          - web.local

  api:
    image: node:14
    networks:
      frontend:
        aliases:
          - api.local
      backend:
        aliases:
          - api.backend

  db:
    image: postgres:12
    networks:
      backend:
        aliases:
          - db.backend

networks:
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.18.0.0/16
  backend:
    driver: bridge
    internal: true
    ipam:
      config:
        - subnet: 172.19.0.0/16

Docker Compose服务扩展#

扩展Docker Compose服务:

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    deploy:
      replicas: 3

  worker:
    image: myapp:worker
    deploy:
      replicas: 5
      restart_policy:
        condition: on-failure

# 使用Docker Swarm部署
docker swarm init
docker-compose up -d

# 扩展服务
docker service scale web=5 worker=10

高级使用#

Docker Compose与CI/CD集成#

将Docker Compose与CI/CD集成:

# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy

build:
  stage: build
  script:
    - docker-compose build
    - docker-compose push

test:
  stage: test
  script:
    - docker-compose up -d
    - docker-compose exec web npm test
    - docker-compose down

deploy:
  stage: deploy
  script:
    - docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
  only:
    - main

# .travis.yml
language: bash
services:
  - docker

script:
  - docker-compose build
  - docker-compose up -d
  - docker-compose exec web npm test
  - docker-compose down

deploy:
  provider: script
  script: docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
  on:
    branch: main

Docker Compose监控#

监控Docker Compose服务:

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"

  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana

volumes:
  grafana_data:

# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'docker'
    static_configs:
      - targets: ['cadvisor:8080']

  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

Docker Compose生产部署#

生产环境部署Docker Compose应用:

# docker-compose.yml
version: '3'
services:
  web:
    image: myapp:latest
    ports:
      - "80:80"
    volumes:
      - static_files:/app/static
      - media_files:/app/media
    environment:
      - DEBUG=0
      - APP_ENV=production
      - DATABASE_URL=postgres://user:password@db:5432/mydb
    restart: always
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G

  db:
    image: postgres:12
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=password
      - POSTGRES_USER=user
      - POSTGRES_DB=mydb
    restart: always
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  redis:
    image: redis:6
    volumes:
      - redis_data:/data
    restart: always
    deploy:
      resources:
        limits:
          cpus: '0.25'
          memory: 256M

volumes:
  static_files:
  media_files:
  postgres_data:
  redis_data:

# 生产部署
docker-compose -f docker-compose.yml up -d

# 配置日志轮转
# /etc/logrotate.d/docker-compose
/var/lib/docker/containers/*/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    copytruncate
}

大师级使用#

Docker Compose多阶段部署#

使用Docker Compose进行多阶段部署:

# docker-compose.yml
version: '3'
services:
  # 构建阶段
  builder:
    build:
      context: .
      dockerfile: Dockerfile.builder
    volumes:
      - ./dist:/app/dist

  # 测试阶段
  tester:
    build:
      context: .
      dockerfile: Dockerfile.tester
    depends_on:
      - builder
      - db
    volumes:
      - ./dist:/app/dist

  # 部署阶段
  web:
    build:
      context: .
      dockerfile: Dockerfile.prod
    ports:
      - "80:80"
    depends_on:
      - db
    volumes:
      - static_files:/app/static

  db:
    image: postgres:12
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  static_files:
  postgres_data:

# 运行构建和测试
docker-compose run builder
docker-compose run tester

# 部署应用
docker-compose up -d web db

Docker Compose与Kubernetes集成#

将Docker Compose与Kubernetes集成:

# 安装kompose
curl -L https://github.com/kubernetes/kompose/releases/download/v1.22.0/kompose-linux-amd64 -o /usr/local/bin/kompose
chmod +x /usr/local/bin/kompose

# 将Docker Compose文件转换为Kubernetes资源
kompose convert -f docker-compose.yml

# 部署到Kubernetes
kubectl apply -f ./

# 查看部署状态
kubectl get pods

# 或者使用Docker Compose for Kubernetes
docker stack deploy --compose-file docker-compose.yml myapp

Docker Compose安全最佳实践#

Docker Compose安全最佳实践:

# docker-compose.yml
version: '3'
services:
  web:
    image: myapp:latest
    ports:
      - "80:80"
    user: "1000:1000"
    read_only: true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    security_opt:
      - no-new-privileges:true
    volumes:
      - static_files:/app/static:ro
      - /tmp:/tmp

  db:
    image: postgres:12
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password
    secrets:
      - postgres_password

secrets:
  postgres_password:
    file: ./postgres_password.txt

volumes:
  static_files:
  postgres_data:

# 生成密码
openssl rand -base64 32 > postgres_password.txt

# 启动服务
docker-compose up -d

实战案例#

案例一:部署WordPress#

场景:部署一个WordPress网站,包含WordPress和MySQL。

解决方案:使用Docker Compose部署WordPress和MySQL。

实施步骤

  1. 创建Docker Compose文件

    # docker-compose.yml
    version: '3'
    services:
      wordpress:
        image: wordpress:latest
        ports:
          - "80:80"
        environment:
          WORDPRESS_DB_HOST: db:3306
          WORDPRESS_DB_USER: wordpress
          WORDPRESS_DB_PASSWORD: wordpress
          WORDPRESS_DB_NAME: wordpress
        volumes:
          - wordpress_data:/var/www/html
        restart: always
    
      db:
        image: mysql:5.7
        environment:
          MYSQL_DATABASE: wordpress
          MYSQL_USER: wordpress
          MYSQL_PASSWORD: wordpress
          MYSQL_ROOT_PASSWORD: root_password
        volumes:
          - db_data:/var/lib/mysql
        restart: always
    
    volumes:
      wordpress_data:
      db_data:
  2. 启动服务

    docker-compose up -d
  3. 访问WordPress

    • 打开浏览器,访问 http://localhost
    • 按照WordPress安装向导完成安装

结果

  • 成功部署了WordPress网站
  • 配置了MySQL数据库
  • WordPress可以正常访问和使用

案例二:部署微服务应用#

场景:部署一个包含前端、后端和数据库的微服务应用。

解决方案:使用Docker Compose部署微服务应用。

实施步骤

  1. 创建Docker Compose文件

    # docker-compose.yml
    version: '3'
    services:
      frontend:
        build: ./frontend
        ports:
          - "3000:3000"
        depends_on:
          - backend
        environment:
          - REACT_APP_API_URL=http://backend:8000
    
      backend:
        build: ./backend
        ports:
          - "8000:8000"
        depends_on:
          - db
        environment:
          - DATABASE_URL=postgres://user:password@db:5432/mydb
    
      db:
        image: postgres:12
        volumes:
          - postgres_data:/var/lib/postgresql/data
        environment:
          - POSTGRES_PASSWORD=password
          - POSTGRES_USER=user
          - POSTGRES_DB=mydb
    
    volumes:
      postgres_data:
  2. 构建和启动服务

    docker-compose build
    docker-compose up -d
  3. 访问应用

    • 前端:http://localhost:3000
    • 后端API:http://localhost:8000/api

结果

  • 成功部署了微服务应用
  • 配置了前端、后端和数据库服务
  • 服务之间可以正常通信

案例三:部署ELK Stack#

场景:部署ELK Stack(Elasticsearch、Logstash、Kibana)用于日志收集和分析。

解决方案:使用Docker Compose部署ELK Stack。

实施步骤

  1. 创建Docker Compose文件

    # docker-compose.yml
    version: '3'
    services:
      elasticsearch:
        image: docker.elastic.co/elasticsearch/elasticsearch:7.10.0
        environment:
          - discovery.type=single-node
          - ES_JAVA_OPTS=-Xms512m -Xmx512m
        ports:
          - "9200:9200"
        volumes:
          - es_data:/usr/share/elasticsearch/data
    
      logstash:
        image: docker.elastic.co/logstash/logstash:7.10.0
        ports:
          - "5044:5044"
        volumes:
          - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
        depends_on:
          - elasticsearch
    
      kibana:
        image: docker.elastic.co/kibana/kibana:7.10.0
        ports:
          - "5601:5601"
        depends_on:
          - elasticsearch
    
    volumes:
      es_data:
  2. 创建Logstash配置文件

    # logstash.conf
    input {
      beats {
        port => 5044
      }
    }
    
    filter {
      grok {
        match => { "message" => "%{COMBINEDAPACHELOG}" }
      }
      date {
        match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
        target => "@timestamp"
      }
    }
    
    output {
      elasticsearch {
        hosts => ["elasticsearch:9200"]
        index => "logs-%{+YYYY.MM.dd}"
      }
    }
  3. 启动服务

    docker-compose up -d
  4. 访问Kibana

    • 打开浏览器,访问 http://localhost:5601
    • 配置索引模式:logs-*

结果

  • 成功部署了ELK Stack
  • 配置了日志收集和分析系统
  • 可以通过Kibana查看和分析日志

总结#

Docker Compose是一种强大的工具,通过本教程的学习,您已经掌握了从入门到大师级的Docker Compose使用技术。

主要技术回顾#

  • 基础操作:Docker Compose的基本命令和操作
  • 服务配置:配置服务的镜像、端口、卷等
  • 网络配置:配置服务之间的通信网络
  • 存储配置:配置服务的持久化存储
  • 环境配置:配置服务的环境变量
  • 多环境配置:配置开发、测试和生产环境
  • 高级功能:健康检查、构建配置、CI/CD集成
  • 企业级应用:生产部署、监控、安全最佳实践

最佳实践#

  1. 版本控制:将Docker Compose文件纳入版本控制,确保配置的一致性
  2. 环境变量:使用环境变量和.env文件管理配置,避免硬编码敏感信息
  3. 健康检查:为服务配置健康检查,确保服务的可用性
  4. 资源限制:为服务设置资源限制,避免资源争用
  5. 卷管理:使用命名卷管理数据,避免数据丢失
  6. 网络隔离:为不同的服务创建独立的网络,提高安全性
  7. 监控服务:使用Prometheus和Grafana监控服务状态
  8. 自动化部署:与CI/CD集成,实现自动化构建、测试和部署
  9. 安全加固:使用非特权容器,配置适当的capabilities,提高安全性
  10. 文档化:为Docker Compose配置添加注释,提高可维护性

注意事项#

  1. 版本兼容性:确保Docker Compose文件版本与Docker Engine版本兼容
  2. 性能优化:根据硬件环境优化服务的资源配置
  3. 网络配置:合理配置网络,确保服务间通信安全
  4. 存储管理:定期清理未使用的卷,释放存储空间
  5. 安全审计:定期进行安全审计,发现和修复安全问题
  6. 备份策略:制定数据备份策略,确保数据安全
  7. 灾难恢复:建立灾难恢复计划,应对突发情况
  8. 依赖管理:明确服务之间的依赖关系,确保服务按正确顺序启动

通过合理学习和使用Docker Compose,您可以显著提高多容器应用的开发、测试和部署效率。Docker Compose已经成为现代微服务架构的标准工具之一,掌握Docker Compose技术将为您的职业发展带来更多机会。