4. Docker Compose 入门:docker-compose.yml 结构、服务定义、网络与卷的声明

在单机 Docker 环境中,当后端鉴权系统涉及多个容器(如 API 网关、鉴权服务、用户服务、Redis 缓存、MySQL 数据库)时,手动执行 docker run 命令逐一启动、配置网络和挂载卷将变得极其繁琐且容易出错。Docker Compose 正是为解决多容器编排而生——它通过一个声明式的 docker-compose.yml 文件,定义整个应用栈的服务、网络和存储,一条命令即可完成启动、停止和重建。

核心概念:Docker Compose 将基础设施视为代码(Infrastructure as Code),让后端鉴权拦截场景下的多服务部署变得可重复、可版本控制。

4.1 docker-compose.yml 文件结构

docker-compose.yml 是 Compose 的核心配置文件,采用 YAML 格式。一个标准的文件包含三个顶级声明块:services、networks 和 volumes。以下是一个后端鉴权场景的典型结构骨架:

version: '3.8'

services:
  # 服务定义区

networks:
  # 网络定义区

volumes:
  # 卷定义区
顶级字段 必填 作用说明
version 是 指定 Compose 文件格式版本,推荐 3.8 或更高版本,以支持最新特性。
services 是 定义应用包含的所有容器服务,每个服务对应一个镜像和运行配置。
networks 否 声明自定义网络,用于服务间的隔离与通信。不声明时使用默认网络。
volumes 否 声明命名卷,用于持久化数据或容器间共享数据。不声明时使用匿名卷。
版本选择建议:对于后端鉴权项目,使用 version: '3.8' 可同时支持 Swarm 模式部署,为后续扩展留有余地。
docker-compose.yml 三层结构 docker-compose.yml services networks volumes 服务定义 api-gateway auth-service redis / mysql 网络声明 frontend_net backend_net 隔离与通信规则 卷声明 mysql_data redis_data 持久化存储

4.2 服务定义详解

每个服务在 services 块下以服务名作为键,其值包含镜像、端口映射、环境变量、依赖关系等配置。以下是一个后端鉴权拦截场景的完整服务定义示例:

version: '3.8'

services:
  api-gateway:
    image: nginx:1.25-alpine
    ports:
      - "8080:80"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
    networks:
      - frontend_net
      - backend_net
    depends_on:
      - auth-service

  auth-service:
    build: ./auth
    image: auth-service:latest
    environment:
      - DB_HOST=mysql
      - REDIS_HOST=redis
      - JWT_SECRET=${JWT_SECRET}
    ports:
      - "3000:3000"
    networks:
      - backend_net
    depends_on:
      - mysql
      - redis

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    networks:
      - backend_net

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: auth_db
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - backend_net
服务配置字段 说明 鉴权场景典型值
image 指定使用的镜像,可以是官方镜像或私有仓库镜像 nginx:1.25-alpine、redis:7-alpine
build 指定 Dockerfile 路径,用于本地构建镜像 ./auth(自定义鉴权服务)
ports 宿主机端口与容器端口映射,格式 "宿主机:容器" "8080:80"(网关对外暴露)
environment 设置容器内的环境变量,支持 ${VAR} 引用宿主变量 JWT_SECRET、DB_HOST
depends_on 声明服务启动顺序依赖,但不等待服务就绪 auth-service 依赖 mysql 和 redis
volumes 挂载卷或绑定挂载,用于持久化或配置注入 redis_data:/data(命名卷)
networks 将服务加入一个或多个自定义网络 frontend_net、backend_net
注意:depends_on 只控制容器启动顺序,不保证内部服务已就绪。对于鉴权服务依赖数据库的场景,建议在应用代码中加入重试机制或使用 healthcheck。

4.3 网络声明与隔离策略

在微服务架构中,网络隔离是安全的基础。Docker Compose 允许声明多个自定义网络,实现服务间的逻辑隔离。对于后端鉴权拦截场景,通常采用前后端分离网络策略:

  • frontend_net:API 网关对外暴露,接收客户端请求。
  • backend_net:鉴权服务、Redis、MySQL 等内部服务在此网络通信,不对外暴露。
networks:
  frontend_net:
    driver: bridge
    ipam:
      config:
        - subnet: "172.20.0.0/24"
  backend_net:
    driver: bridge
    internal: true   # 禁止外部访问,仅内部容器通信
    ipam:
      config:
        - subnet: "172.20.1.0/24"
网络属性 frontend_net backend_net
驱动 bridge bridge
外部访问 允许(通过端口映射) 禁止(internal: true)
子网 172.20.0.0/24 172.20.1.0/24
包含服务 api-gateway auth-service, redis, mysql
安全最佳实践:将数据库和缓存服务置于 internal 网络中,即使容器被攻破,攻击者也无法从外部直接访问数据层。
后端鉴权网络隔离架构 外部客户端 frontend_net (172.20.0.0/24) API 网关 (nginx) backend_net (172.20.1.0/24) [internal] 鉴权服务 (auth-service) Redis MySQL API 网关同时加入两个网络,作为前后端通信的唯一桥梁

4.4 卷的声明与数据持久化

容器默认是 ephemeral(临时)的,容器删除后数据即丢失。对于鉴权系统,用户信息、令牌黑名单、审计日志等数据必须持久化。Docker Compose 通过 volumes 块声明命名卷,然后在服务中引用。

volumes:
  mysql_data:
    driver: local
  redis_data:
    driver: local
  auth_logs:
    driver: local

在服务中使用命名卷:

services:
  mysql:
    image: mysql:8.0
    volumes:
      - mysql_data:/var/lib/mysql   # 命名卷,数据持久化
      - ./init-scripts:/docker-entrypoint-initdb.d  # 绑定挂载,初始化脚本

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

  auth-service:
    build: ./auth
    volumes:
      - auth_logs:/app/logs         # 日志持久化
      - ./auth/config:/app/config   # 配置文件绑定挂载
卷类型 声明位置 生命周期 适用场景
命名卷(Named Volume) volumes 顶级块 独立于容器,docker compose down 默认不删除 数据库数据、缓存数据、持久化日志
绑定挂载(Bind Mount) 服务内直接指定宿主机路径 依赖宿主机文件系统 配置文件、开发热重载、初始化脚本
匿名卷(Anonymous Volume) 服务内只写容器路径 容器删除后自动清理 临时缓存、不重要的中间数据
生产建议:对于 MySQL 和 Redis 的数据卷,始终使用命名卷并定期备份。绑定挂载适合开发环境,生产环境应避免将敏感配置文件直接挂载到宿主机。

4.5 常用 Compose 命令速查

编写完 docker-compose.yml 后,通过以下命令管理整个应用栈:

# 启动所有服务(后台模式)
docker compose up -d

# 查看服务状态
docker compose ps

# 查看日志(实时跟踪)
docker compose logs -f auth-service

# 停止并移除容器、网络(默认保留卷)
docker compose down

# 停止并移除容器、网络、卷(谨慎使用)
docker compose down -v

# 重新构建镜像并启动
docker compose up -d --build

# 进入某个容器
docker compose exec auth-service sh
版本说明:新版 Docker 已将 docker-compose(带横线)整合为 docker compose(子命令),功能完全兼容。建议使用 docker compose 命令。