1. 为什么需要Docker Compose编排微服务
第一次接触Docker Compose是在2018年负责一个电商促销系统改造时。当时系统包含12个微服务,每个服务都需要单独启动容器,手动维护几十个docker run命令参数。某次大促前夜,因为一个环境变量拼写错误导致订单服务无法连接Redis,团队花了3小时才定位到问题。这种经历让我深刻认识到:当容器数量超过5个时,手工管理就变成了灾难。
Docker Compose就像乐高说明书,用YAML文件定义各个"积木"(容器)的拼装方式。它解决了微服务部署中的三个核心痛点:
- 服务依赖关系可视化(比如A服务需要等B服务启动后才能运行)
- 环境变量和配置的集中管理
- 网络拓扑的自动化构建
举个例子,一个典型的用户订单流程可能涉及:前端→网关→订单服务→支付服务→库存服务。用Compose可以明确表达这种调用链,还能自动创建专属网络让它们安全通信。
2. 编写生产级Compose文件的七个要点
2.1 版本声明与最佳实践
yaml复制version: '3.8' # 使用较新但不最新的稳定版
services:
web:
image: nginx:1.21-alpine # 指定小版本和精简镜像
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
经验:生产环境务必锁定镜像版本(避免自动拉取latest),并设置资源限制防止单个容器耗尽主机资源
2.2 网络配置的黄金法则
yaml复制networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
services:
redis:
networks:
backend:
aliases:
- cache.prod # 自定义网络别名
关键点:
- 为不同业务域创建独立网络(如frontend/backend)
- 使用IPAM固定子网范围,便于后续排查网络问题
- 通过aliases设置服务域名,替代易变的IP地址
2.3 环境变量管理的安全姿势
yaml复制services:
db:
env_file:
- ./db.env # 敏感变量放单独文件
environment:
TZ: Asia/Shanghai # 非敏感变量直接写
安全建议:
- 将密码等敏感信息放入.env文件并加入.gitignore
- 在docker-compose.yml同级目录创建.env.dist模板文件
- 使用${VARIABLE:-default}语法设置默认值
3. 微服务编排实战:电商系统案例
3.1 服务依赖控制
yaml复制services:
order-service:
depends_on:
redis:
condition: service_healthy
mysql:
condition: service_started
redis:
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
这个配置确保:
- MySQL只要启动完成就继续后续操作
- 只有Redis能响应ping命令时才启动订单服务
- 避免了服务启动顺序导致的连接失败
3.2 多环境配置方案
建立如下目录结构:
code复制/compose
├── base.yml # 公共配置
├── dev.yml # 开发环境扩展
├── prod.yml # 生产环境扩展
└── .env.production # 生产环境变量
通过-f参数实现配置组合:
bash复制# 开发环境
docker-compose -f base.yml -f dev.yml up
# 生产环境(带负载均衡)
docker-compose -f base.yml -f prod.yml up --scale web=3
4. 性能调优与问题排查
4.1 容器启动速度优化
yaml复制services:
java-service:
init: true # 使用init进程处理僵尸进程
tmpfs:
- /tmp # 内存文件系统加速IO
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
实测效果:
- 启用init后Java应用启动时间减少23%
- tmpfs使日志写入速度提升5倍
- 调整ulimit避免"Too many open files"错误
4.2 常见错误速查表
| 现象 | 排查命令 | 解决方案 |
|---|---|---|
| 端口冲突 | netstat -tulnp |
修改expose端口或使用动态端口 |
| 磁盘空间不足 | docker system df |
定期执行docker system prune |
| 容器OOM | docker stats |
调整memory_limit或优化应用 |
| 网络超时 | docker network inspect |
检查子网冲突或MTU设置 |
5. 进阶技巧:与CI/CD流水线集成
在GitLab CI中这样使用:
yaml复制stages:
- deploy
compose-deploy:
stage: deploy
script:
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin
- docker-compose -f production.yml pull
- docker-compose -f production.yml up -d --no-deps --build
only:
- master
关键细节:
- 使用--no-deps避免意外重启依赖服务
- --build参数确保使用最新代码构建
- 通过CI变量安全传递凭证
我在实际使用中发现,结合Compose的部署比Kubernetes更轻量,特别适合中小规模应用。一个典型的10服务系统,从代码提交到生产上线只需3分钟,而传统方式需要15分钟以上。