背景
在微服务架构下,服务的部署与更新频率远高于传统单体应用。手工SSH登录服务器逐台操作不仅效率低下,还极易因人为失误导致服务中断。本文介绍如何利用Docker Compose结合Nginx实现一套轻量级的微服务自动化部署与灰度发布方案,适用于中小规模团队(5~20个服务节点),无需引入Kubernetes等重型基础设施。
核心思路
- GitOps驱动:代码提交至Git后,通过Webhook触发部署脚本完成服务更新。
- 蓝绿/灰度双轨:通过Nginx upstream权重调整,实现新老版本共存与平滑切换。
- 环境一致性:所有服务以Docker Compose YAML定义,环境差异归零。
目录结构
推荐在每台服务器上建立统一部署目录:
1 2 3 4 5 6 7 8 9 10
| /opt/app/ ├── docker-compose.yml # 主编排文件 ├── .env # 环境变量(版本、镜像TAG) ├── nginx/ │ └── upstream.conf # 动态upstream配置 ├── scripts/ │ ├── deploy.sh # 部署脚本 │ ├── rollback.sh # 回滚脚本 │ └── switch.sh # 灰度切换脚本 └── backup/ # 历史版本备份
|
核心配置
docker-compose.yml 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| version: "3.8" services: api-gateway: image: registry.example.com/api-gateway:${VERSION:-latest} container_name: api-gateway restart: always ports: - "8080:8080" environment: - TZ=Asia/Shanghai networks: - frontend healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3
user-service: image: registry.example.com/user-service:${VERSION:-latest} container_name: user-service restart: always ports: - "8081:8080" depends_on: - api-gateway networks: - backend
networks: frontend: backend:
|
.env 文件内容:
1 2 3
| VERSION=1.2.3 REGISTRY=registry.example.com DEPLOY_TIME=2026-04-02
|
Nginx 灰度upstream配置
1 2 3 4 5
| upstream backend { server 127.0.0.1:8081 weight=10; server 127.0.0.1:8082 weight=0; }
|
部署脚本 deploy.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #!/bin/bash set -euo pipefail ENV_FILE="/opt/app/.env" NGINX_CONF="/opt/app/nginx/upstream.conf"
source "$ENV_FILE"
echo "[$(date)] 开始部署,版本:$VERSION"
docker-compose pull
docker-compose up -d --remove-orphans
sleep 10
if docker inspect --format='{{.State.Health.Status}}' api-gateway | grep -q "healthy"; then echo "[$(date)] 服务健康检查通过" else echo "[$(date)] 健康检查失败,执行回滚" docker-compose down docker-compose -f docker-compose.backup.yml up -d exit 1 fi
|
灰度切换脚本 switch.sh
将新版本容器(监听8082)权重从0调整为5,观察错误率:
1 2 3 4 5 6 7 8
| #!/bin/bash
NEW_WEIGHT=${1:-5}
sed -i "s/weight=0/weight=$NEW_WEIGHT/" /opt/app/nginx/upstream.conf nginx -s reload
echo "[$(date)] 灰度权重调整为:$NEW_WEIGHT"
|
验证方式:
1 2 3 4 5
| curl http://127.0.0.1:8080/nginx_status
watch -n5 "curl -s http://127.0.0.1:8080/api/health | jq '.errors // 0'"
|
回滚脚本 rollback.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #!/bin/bash BACKUP_DIR="/opt/app/backup" LATEST_BACKUP=$(ls -t "$BACKUP_DIR" | head -1)
if [ -z "$LATEST_BACKUP" ]; then echo "[$(date)] 无可用的备份版本" exit 1 fi
echo "[$(date)] 开始回滚至:$LATEST_BACKUP" cp "$BACKUP_DIR/$LATEST_BACKUP/docker-compose.yml" /opt/app/docker-compose.yml docker-compose up -d --remove-orphans nginx -s reload echo "[$(date)] 回滚完成"
|
完整部署流程
- 代码提交 → Git仓库触发Webhook调用部署服务器
/hooks/deploy
- 部署服务器 执行
git pull && ./scripts/deploy.sh
- 新版本容器 以不同端口(如8082)启动,与老版本(8081)并存
- 灰度切换 调用
./scripts/switch.sh 5,5%流量切换新版本
- 监控观察 持续5分钟,错误率稳定后调用
./scripts/switch.sh 10 全量
- 异常回滚 调用
./scripts/rollback.sh
注意事项
.env 文件包含敏感信息,需确保权限为600:chmod 600 /opt/app/.env
- 备份策略建议保留最近5个历史版本,使用
cron 每日清理
- 镜像仓库建议启用镜像签名,防止供应链攻击
- 大规模场景(20+服务节点)建议逐步引入Ansible或SaltStack做批量编排
总结
该方案以Docker Compose为容器编排核心,配合Nginx实现灰度发布,无需额外学习成本即可落地。对于团队规模在20人以内的微服务项目,能够在10~15分钟内完成从代码提交到生产上线的完整闭环,兼顾了部署效率与运行稳定性。