Docker Compose 使用完全指南

1. 什么是Docker Compose?

Docker Compose是Docker官方提供的用于定义和运行多容器Docker应用程序的工具。通过一个简单的YAML文件配置应用程序的所有服务,然后使用单个命令创建并启动所有服务。Docker Compose特别适合开发、测试和CI/CD环境,能够显著简化多容器应用的部署流程。

与Docker CLI相比,Docker Compose的主要优势在于:

集中管理多个容器

一键启动/停止整个应用栈

自动化容器间网络配置

轻松实现服务扩展和负载均衡

完整的开发工作流支持

2. 安装Docker Compose

2.1. Linux系统安装

# 下载Docker Compose二进制文件
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

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

# 创建软链接(可选)
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

# 验证安装
docker-compose version

2.2. macOS系统安装

# 使用Homebrew安装
brew install docker-compose

# 验证安装
docker-compose --version

2.3. Windows系统安装

下载Docker Desktop for Windows:https://www.docker.com/products/docker-desktop

安装时确保启用"Include Docker Compose"选项

安装完成后在PowerShell中验证:

docker-compose version

3. Docker Compose核心概念

3.1. 服务(Services)

服务代表应用中的一个组件,例如Web服务器、数据库、缓存等。在docker-compose.yml文件中定义服务的配置。

3.2. 容器(Containers)

基于服务配置创建的运行实例。每个服务可以包含一个或多个容器实例。

3.3. 网络(Networks)

提供容器间的通信通道。Docker Compose会自动创建默认网络,也可以自定义网络配置。

3.4. 卷(Volumes)

用于持久化数据和容器间共享数据。可以挂载主机目录或使用Docker管理的卷。

3.5. 项目(Projects)

由docker-compose.yml文件定义的一组关联服务。项目名称默认为目录名,也可通过-p参数指定。

4. 编写docker-compose.yml文件

docker-compose.yml是Docker Compose的核心配置文件,使用YAML格式定义服务、网络和卷。

4.1. 文件结构示例

version: '3.8'  # Docker Compose文件格式版本

services:      # 服务定义部分
  webapp:      # 服务名称
    image: nginx:alpine  # 使用的基础镜像
    ports:      # 端口映射
      - "8080:80"
    volumes:    # 数据卷挂载
      - ./html:/usr/share/nginx/html
    networks:   # 使用的网络
      - webnet
    depends_on: # 依赖关系
      - database

  database:
    image: mysql:5.7
    environment:  # 环境变量
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: myapp
    volumes:
      - dbdata:/var/lib/mysql
    networks:
      - webnet

volumes:        # 顶级卷定义
  dbdata:       # 命名卷

networks:       # 顶级网络定义
  webnet:       # 自定义网络
    driver: bridge

4.2. 指令详解

version:指定Docker Compose文件格式版本

services:定义所有服务

image:指定镜像(优先使用本地镜像,不存在则拉取)

build:从Dockerfile构建镜像

build:
  context: ./dir        # 构建上下文路径
  dockerfile: Dockerfile-dev  # 自定义Dockerfile名称
  args:                # 构建参数
    BUILD_VERSION: 1.0

ports:端口映射(主机:容器)

ports:
  - "8080:80"          # 主机8080端口映射到容器80端口
  - "9000-9010:9000"   # 主机端口范围映射

volumes:数据卷挂载

volumes:
  - ./html:/usr/share/nginx/html  # 绑定挂载(主机目录:容器目录)
  - dbdata:/var/lib/mysql         # 命名卷(卷名:容器路径)
  - /data:/data:ro                # 只读挂载

environment:环境变量

environment:
  - DEBUG=true
  - DB_HOST=database
  - PASSWORD=secret  # 敏感信息建议使用环境文件

env_file:从文件加载环境变量

env_file:
  - ./common.env
  - ./apps/web.env

depends_on:服务依赖顺序

depends_on:
  - database
  - redis

networks:网络配置

networks:
  - frontnet
  - backnet

command:覆盖容器默认命令

command: python manage.py runserver 0.0.0.0:8000

restart:重启策略

restart: unless-stopped  # 选项:no, always, on-failure, unless-stopped

healthcheck:健康检查

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]
  interval: 30s
  timeout: 10s
  retries: 3

secrets:敏感数据管理(需Swarm模式)

secrets:
  - db_password
secrets:
  db_password:
    file: ./db_password.txt

volumes:顶级卷定义(可选)

networks:顶级网络定义(可选)

4.3. 完整示例:WordPress应用

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
    networks:
      - wpnet
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 20s
      timeout: 10s
      retries: 5

  wordpress:
    depends_on:
      db:
        condition: service_healthy
    image: wordpress:latest
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - ./wp-content:/var/www/html/wp-content
    networks:
      - wpnet

volumes:
  db_data:

networks:
  wpnet:
    driver: bridge

5. Docker Compose命令详解

5.1. 基本命令格式

docker-compose [选项] [命令] [服务]

5.2. 常用命令

构建和启动

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

# 构建镜像后启动(适用于使用build指令的服务)
docker-compose up --build

# 启动特定服务
docker-compose up -d webapp

停止和删除

# 停止所有服务
docker-compose stop

# 停止并删除容器、网络、卷(保留命名卷)
docker-compose down

# 停止并删除所有资源(包括命名卷)
docker-compose down -v

# 删除停止的服务容器
docker-compose rm -f

查看状态

# 列出所有容器
docker-compose ps

# 查看服务日志(实时跟踪)
docker-compose logs -f webapp

# 查看最后20条日志
docker-compose logs --tail=20

服务操作

# 启动已停止的服务
docker-compose start db

# 停止运行中的服务
docker-compose stop webapp

# 重启服务
docker-compose restart webapp

# 构建或重新构建服务
docker-compose build webapp

# 强制重新构建(不使用缓存)
docker-compose build --no-cache

容器内操作

# 在容器内执行命令(交互式)
docker-compose exec webapp bash

# 在容器内执行单个命令
docker-compose exec db mysql -u root -p

扩展服务

# 启动3个web实例
docker-compose up -d --scale webapp=3

# 查看扩展结果
docker-compose ps

5.3. 高级选项

指定项目名称

docker-compose -p myproject up -d

使用自定义配置文件

docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

强制重新创建容器

docker-compose up -d --force-recreate

不使用缓存启动

docker-compose up -d --force-recreate --build --no-deps

6. 网络配置详解

6.1. 默认网络行为

Docker Compose自动创建名为<项目名>_default的网络

所有服务加入该默认网络

服务名可作为主机名在容器间访问

6.2. 自定义网络

version: '3.8'

services:
  frontend:
    image: nginx
    networks:
      - frontend
      - backend

  backend:
    image: myapp
    networks:
      - backend
      - database

  database:
    image: mysql
    networks:
      - database

networks:
  frontend:
    driver: bridge

  backend:
    driver: bridge

  database:
    driver: bridge
    internal: true  # 禁止外部访问

6.3. 网络高级配置

networks:
  mynet:
    driver: overlay      # 用于Swarm集群
    driver_opts:
      com.docker.network.enable_ipv6: "true"
    ipam:
      driver: default
      config:
        - subnet: 172.20.0.0/16
          gateway: 172.20.0.1

7. 数据卷管理

7.1. 卷类型对比

| 类型 | 特点 | 适用场景 |

|------|------|----------|

| 绑定挂载 | 直接映射主机目录 | 开发时实时同步 |

| 命名卷 | Docker管理 | 生产环境持久化 |

| 临时卷 | 容器内目录 | 临时数据处理 |

7.2. 卷配置示例

version: '3.8'

services:
  app:
    image: myapp
    volumes:
      # 绑定挂载(开发时使用)
      - ./src:/app/src

      # 命名卷(生产环境)
      - app_data:/app/data

      # 只读挂载
      - ./config:/app/config:ro

      # 临时卷
      - temp_data:/tmp

volumes:
  app_data:     # 命名卷
  temp_data:    # 临时卷

7.3. 卷高级选项

volumes:
  data:
    driver: local
    driver_opts:
      type: none          # 使用NFS
      o: bind
      device: /nfs/data   # NFS路径

8. 环境变量管理

8.1. 环境变量优先级

docker-compose.yml中定义的environment

env_file中定义的变量

主机环境变量(通过--env-file指定)

8.2. 环境变量使用技巧

在docker-compose.yml中引用变量

web:
  image: "${WEB_IMAGE_TAG:-latest}"
  environment:
    - API_KEY=${API_KEY}
  command: ["${START_CMD}", "run"]

使用.env文件

# .env文件内容
DB_HOST=db
DB_PORT=3306
DB_USER=wordpress
# docker-compose.yml
db:
  image: mysql:${DB_VERSION}
  environment:
    MYSQL_USER: ${DB_USER}
    MYSQL_PASSWORD: ${DB_PASSWORD}
  env_file:
    - .env

覆盖环境变量

# 使用不同环境变量文件
docker-compose --env-file .env.prod up -d

# 直接设置环境变量
DB_PASSWORD=secret docker-compose up -d

9. 多环境配置

9.1. 开发环境配置

docker-compose.dev.yml

version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - .:/app
    environment:
      - DEBUG=true
    ports:
      - "5000:5000"

9.2. 生产环境配置

docker-compose.prod.yml

version: '3.8'
services:
  app:
    image: myregistry/myapp:latest
    environment:
      - DEBUG=false
      - DB_HOST=prod.db.example.com
    restart: always
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

9.3. 使用方式

# 开发环境
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

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

10. 健康检查配置

10.1. 基本健康检查

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

10.2. 高级健康检查

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

10.3. 依赖健康检查

services:
  app:
    image: myapp
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started  # 只需要启动,不需要健康

11. 实战案例:多容器Web应用部署

11.1. 项目结构

myproject/
├── docker-compose.yml
├── Dockerfile
├── app/
│   ├── __init__.py
│   ├── app.py
│   └── requirements.txt
└── nginx/
    └── nginx.conf

11.2. 应用代码

app.py

from flask import Flask, jsonify
import os
import redis
import time

app = Flask(__name__)

# 从环境变量获取配置
REDIS_HOST = os.getenv('REDIS_HOST', 'redis')
REDIS_PORT = int(os.getenv('REDIS_PORT', 6379))

# 连接Redis
cache = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)

@app.route('/')
def hello():
    count = cache.incr('hits')
    return jsonify(hello='world', visitor_count=count)

@app.route('/time')
def current_time():
    return jsonify(time=time.ctime())

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)

11.3. Dockerfile

FROM python:3.9-slim

WORKDIR /app

COPY ./app/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY ./app .

CMD ["flask", "run", "--host=0.0.0.0"]

11.4. Nginx配置

nginx.conf

server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://app:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

11.5. Docker Compose配置

docker-compose.yml

version: '3.8'

services:
  app:
    build: .
    restart: always
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    depends_on:
      - redis
    networks:
      - appnet

  redis:
    image: redis:alpine
    restart: always
    volumes:
      - redis_data:/data
    networks:
      - appnet
    command: redis-server --appendonly yes

  nginx:
    image: nginx:alpine
    restart: always
    ports:
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app
    networks:
      - appnet

volumes:
  redis_data:

networks:
  appnet:
    driver: bridge

11.6. 部署步骤

克隆项目或创建上述文件结构

构建并启动服务:

docker-compose up -d --build

验证服务:

curl http://localhost

查看日志:

docker-compose logs -f

停止服务:

docker-compose down

12. 最佳实践

版本控制:始终使用特定版本的Docker镜像

image: redis:6.2-alpine  # 而不是 redis:latest

安全配置:

使用非root用户运行容器

通过env_file管理敏感信息

限制容器资源

deploy:
  resources:
    limits:
      cpus: '0.5'
      memory: 512M

可维护性:

为服务添加健康检查

使用restart策略

添加元数据标签

labels:
  com.example.description: "Web application service"

环境隔离:

使用不同项目名称(-p参数)

为不同环境创建不同的compose文件

日志管理:

配置日志驱动

logging:
  driver: "json-file"
  options:
    max-size: "100m"
    max-file: "3"

性能优化:

使用多阶段构建减小镜像体积

合理使用数据卷

避免不必要的依赖

13. 总结

Docker Compose是容器化应用开发、测试和部署的强大工具,通过本文的详细介绍,您应该已经掌握了:

Docker Compose的核心概念和安装方法

docker-compose.yml文件的编写技巧和完整指令集

从单容器到多容器应用的部署流程

网络配置和数据卷管理的高级用法

环境变量和多环境配置策略

健康检查和依赖关系配置

实际项目部署的完整案例

生产环境最佳实践

Docker Compose通过声明式配置显著简化了容器编排工作,特别适合开发团队快速搭建一致的开发、测试环境,也为生产环境的微服务部署提供了标准化方案。随着对Docker生态的深入探索,您可以将Compose与Docker Swarm、Kubernetes等工具结合使用,构建更复杂的分布式系统。

要持续提升Docker Compose技能,建议:

定期查阅[Docker官方文档](https://docs.docker.com/compose/)

尝试将现有项目容器化

探索Docker Compose与CI/CD工具的集成

研究Docker Stack(Swarm模式下的Compose)

通过不断实践和深入理解容器化技术,您将能够构建更健壮、可扩展的现代化应用架构。

发表回复

后才能评论