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 模式部署,为后续扩展留有余地。
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 网络中,即使容器被攻破,攻击者也无法从外部直接访问数据层。
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 命令。