4. Docker Compose 编排:服务定义、网络配置、依赖管理、环境变量
在微服务架构中,Docker Compose 是定义和运行多容器 Docker 应用的核心工具。本章聚焦于 Compose 文件的四大关键要素:服务定义、网络配置、依赖管理与环境变量。掌握这些要素,是构建可复现、可调试的微服务环境的基础。
4.1 服务定义:微服务的声明式描述
每个微服务在 docker-compose.yml 中对应一个 services 下的顶级键。服务定义的核心字段包括镜像来源、容器名称、端口映射、卷挂载以及重启策略。
| 字段 | 说明 | 常见值示例 |
|---|---|---|
image |
指定使用的镜像,支持私有仓库地址 | registry.example.com/user/api:v1.2 |
build |
从 Dockerfile 构建镜像,可指定上下文路径 | ./api |
ports |
宿主机端口与容器端口的映射关系 | "8080:8080" |
volumes |
持久化数据或挂载配置文件 | ./config:/app/config:ro |
restart |
容器退出后的重启策略 | unless-stopped |
故障排查要点: 服务定义中
container_name 若重复,Compose 会报错;ports 映射冲突(宿主机端口已被占用)是启动失败的常见原因,排查时优先检查端口占用情况。
version: "3.8"
services:
user-service:
image: myregistry/user-service:1.0.0
container_name: user-svc
ports:
- "8081:8080"
volumes:
- ./logs/user:/var/log/app
restart: unless-stopped
order-service:
build: ./order
ports:
- "8082:8080"
restart: on-failure:3
4.2 网络配置:服务间通信的骨架
Docker Compose 默认创建一个名为 <项目名>_default 的桥接网络,所有服务自动加入该网络并通过服务名互相访问。但在微服务架构中,通常需要自定义网络来实现隔离、分层或跨主机通信。
最佳实践: 为前端网关、业务服务、数据层分别创建独立的网络,仅暴露必要的通信路径,减少攻击面。
networks:
frontend:
driver: bridge
backend:
driver: bridge
database:
driver: bridge
services:
api-gateway:
networks:
- frontend
- backend
user-service:
networks:
- backend
- database
postgres:
networks:
- database
4.3 依赖管理:控制启动顺序与健康检查
微服务之间存在启动顺序依赖,例如订单服务需要等待用户服务就绪。Compose 提供 depends_on 声明依赖关系,但该字段仅控制容器启动顺序,不保证服务内部进程已就绪。生产环境应配合 healthcheck 实现真正的依赖等待。
| 机制 | 作用 | 局限性 |
|---|---|---|
depends_on |
控制容器创建与启动顺序 | 不等待服务内部就绪,仅保证容器已启动 |
healthcheck |
定期检查容器内进程是否健康 | 需要服务暴露健康端点或支持命令检测 |
condition: service_healthy |
在 depends_on 中等待健康状态 | Compose v3.8+ 支持,需配合 healthcheck 使用 |
常见故障: 仅使用
depends_on 而未配置健康检查,导致依赖服务尚未完成数据库迁移或缓存预热,上游服务连接失败。排查时观察容器日志中的连接重试与超时信息。
services:
postgres:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
timeout: 3s
retries: 5
user-service:
image: user-service:1.0
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 10s
timeout: 5s
retries: 3
order-service:
image: order-service:1.0
depends_on:
user-service:
condition: service_healthy
postgres:
condition: service_healthy
4.4 环境变量:配置注入与多环境管理
环境变量是微服务配置注入的标准方式,Compose 支持多种注入途径:直接在 environment 字段定义、引用宿主机变量、使用 .env 文件批量加载。
- 直接定义: 适用于少量固定值,如
SPRING_PROFILES_ACTIVE=prod。 - 宿主机变量引用: 使用
${HOST_VAR}语法,敏感信息可通过宿主机环境传入。 - .env 文件: 项目根目录下的
.env文件自动加载,适合管理多环境差异。
故障排查技巧: 使用
docker compose config 命令查看 Compose 文件解析后的最终配置,确认环境变量是否被正确替换。若变量未定义,Compose 会保留 ${VAR} 字面量,导致服务启动异常。
# .env 文件
DB_HOST=postgres
DB_PORT=5432
DB_USER=app_user
DB_PASSWORD=${DB_PASSWORD} # 从宿主机环境读取,不写入文件
# docker-compose.yml
services:
user-service:
image: user-service:1.0
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
env_file:
- ./config/common.env
4.5 综合编排示例:三服务微服务栈
以下是一个包含 API 网关、用户服务、PostgreSQL 的完整编排示例,整合了服务定义、网络隔离、健康检查依赖与环境变量管理。
version: "3.8"
networks:
frontend:
driver: bridge
backend:
driver: bridge
services:
api-gateway:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- frontend
- backend
depends_on:
user-service:
condition: service_healthy
restart: unless-stopped
user-service:
image: user-service:1.0.0
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_HOST=postgres
- DB_PORT=5432
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
networks:
- backend
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 10s
timeout: 5s
retries: 3
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
postgres:
image: postgres:15
environment:
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=userdb
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
volumes:
pgdata:
调试命令速查:
docker compose config — 验证 Compose 文件语法与变量替换docker compose ps — 查看服务运行状态与端口映射docker compose logs -f <service> — 跟踪特定服务的实时日志docker compose exec <service> sh — 进入容器内部排查网络连通性