3. Docker Compose 入门:Compose文件结构、服务定义、网络与卷的声明、常用Compose命令

在搭建缓存一致性测试环境时,多个容器(如 Redis 主从、Sentinel、应用模拟器)需要协同工作。手动管理每个容器的启动顺序、网络连接和数据持久化非常繁琐。Docker Compose 正是解决这一问题的利器——它通过一个声明式 YAML 文件,定义整个多容器应用栈,实现一键部署与销毁。

3.1 Compose 文件结构

Compose 文件(默认名为 docker-compose.yml 或 compose.yaml)采用 YAML 格式,顶层结构固定为三个主要区块:services、networks 和 volumes。此外,version 字段在 Compose V2 中已废弃,但旧版文件仍可能保留。

顶层区块 作用 是否必选
services 定义每个容器的镜像、端口、环境变量、依赖关系等 必选
networks 声明自定义网络,实现服务间隔离与通信 可选(默认使用 default 网络)
volumes 声明持久化卷或绑定挂载,用于数据持久化 可选
最佳实践:始终显式声明 networks 和 volumes,即使只使用默认值。这能提升文件可读性,并避免后续扩展时遗漏配置。
docker-compose.yml 三层结构 services 定义容器:镜像、端口、环境、依赖、命令 networks 声明自定义网络,控制服务间通信 volumes 声明持久化卷,实现数据持久化

3.2 服务定义详解

每个服务对应一个容器。以下是一个缓存测试场景中典型的服务定义示例,包含 Redis 主节点和 Sentinel 节点:

services:
  redis-master:
    image: redis:7-alpine
    container_name: cache-master
    ports:
      - "6379:6379"
    volumes:
      - master-data:/data
      - ./config/redis-master.conf:/usr/local/etc/redis/redis.conf
    networks:
      - cache-net
    command: ["redis-server", "/usr/local/etc/redis/redis.conf"]

  sentinel-1:
    image: redis:7-alpine
    container_name: sentinel-1
    ports:
      - "26379:26379"
    volumes:
      - ./config/sentinel.conf:/usr/local/etc/redis/sentinel.conf
    networks:
      - cache-net
    depends_on:
      - redis-master
    command: ["redis-sentinel", "/usr/local/etc/redis/sentinel.conf"]
字段 说明 缓存测试场景示例
image 指定容器镜像,支持标签 redis:7-alpine(轻量 Redis 镜像)
container_name 自定义容器名称,便于识别 cache-master
ports 宿主机端口:容器端口映射 "6379:6379"
volumes 挂载卷或绑定宿主机路径 持久化 RDB/AOF 文件、挂载配置文件
networks 加入的自定义网络 cache-net
depends_on 声明启动顺序依赖 Sentinel 依赖 Master 先启动
command 覆盖 Dockerfile 中的 CMD 指定配置文件启动 Redis
注意:depends_on 仅控制容器启动顺序,不保证服务就绪。在缓存一致性测试中,建议配合 healthcheck 或等待脚本,确保主节点完全启动后再启动 Sentinel。

3.3 网络与卷的声明

在 Compose 文件中,网络和卷需要在顶层声明,然后在服务中引用。这种分离设计使得网络拓扑和存储策略可以独立复用。

网络声明

networks:
  cache-net:
    driver: bridge
    ipam:
      config:
        - subnet: "172.20.0.0/16"
          gateway: "172.20.0.1"

在缓存测试中,自定义网络可以固定子网,便于配置静态 IP 或模拟网络分区故障。如果不指定 driver,默认使用 bridge。

卷声明

volumes:
  master-data:
    driver: local
  sentinel-data:
    driver: local

卷声明后,在服务中通过 volumes: 引用:

services:
  redis-master:
    volumes:
      - master-data:/data

绑定挂载(bind mount)则直接在服务中写宿主机路径,无需在顶层声明:

volumes:
  - ./config/redis-master.conf:/usr/local/etc/redis/redis.conf
网络与卷的声明与引用关系 顶层 networks 声明 cache-net: driver: bridge subnet: 172.20.0.0/16 顶层 volumes 声明 master-data: driver: local sentinel-data: driver: local services 中引用 redis-master: networks: [cache-net] volumes: [master-data:/data] sentinel-1: networks: [cache-net] volumes: [sentinel-data:/data]

3.4 常用 Compose 命令

以下命令覆盖了缓存测试环境从启动到清理的完整生命周期:

命令 作用 缓存测试场景示例
docker compose up -d 后台启动所有服务 启动 Redis 主从 + Sentinel 集群
docker compose down 停止并移除容器、网络 清理测试环境,保留卷数据
docker compose down -v 停止并移除容器、网络、卷 完全重置测试环境,清除所有数据
docker compose ps 查看服务状态 确认所有节点运行正常
docker compose logs -f 实时查看日志 观察主从同步或故障转移日志
docker compose exec <service> <cmd> 在运行中的容器内执行命令 exec redis-master redis-cli info replication
docker compose restart 重启指定或所有服务 模拟节点重启,测试缓存恢复
docker compose config 验证并显示合并后的 Compose 配置 检查多文件合并后的最终配置
效率提示:在缓存一致性测试中,频繁使用 docker compose up -d 和 docker compose down -v 组合,可以快速在“干净状态”和“故障恢复”场景之间切换,大幅缩短测试准备时间。

3.5 完整 Compose 文件示例

以下是一个面向缓存一致性测试的最小化 Compose 文件,包含 Redis 主节点和一个 Sentinel 实例:

version: "3.8"

services:
  redis-master:
    image: redis:7-alpine
    container_name: cache-master
    ports:
      - "6379:6379"
    volumes:
      - master-data:/data
      - ./config/redis-master.conf:/usr/local/etc/redis/redis.conf
    networks:
      cache-net:
        ipv4_address: 172.20.0.10
    command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3

  sentinel-1:
    image: redis:7-alpine
    container_name: sentinel-1
    ports:
      - "26379:26379"
    volumes:
      - ./config/sentinel.conf:/usr/local/etc/redis/sentinel.conf
    networks:
      cache-net:
        ipv4_address: 172.20.0.20
    depends_on:
      redis-master:
        condition: service_healthy
    command: ["redis-sentinel", "/usr/local/etc/redis/sentinel.conf"]

networks:
  cache-net:
    driver: bridge
    ipam:
      config:
        - subnet: "172.20.0.0/16"

volumes:
  master-data:
    driver: local

该示例展示了 healthcheck 与 depends_on.condition 的配合使用,确保 Sentinel 仅在 Master 健康就绪后才启动——这是缓存一致性测试中避免竞态条件的关键配置。