下面提供一个支持多环境、Docker 集成、蓝绿部署的完整方案。包含一个核心部署脚本、示例配置文件和 Docker Compose 配置,适用于微服务或 Web 应用。该方案实现了环境隔离、快速回滚与零停机发布,适合微服务架构下的持续交付。

微服务持续交付Docker蓝绿部署脚本_swarm2k docker界面_多环境Docker集成蓝绿部署方案

该方案的核心要素:

1. 多环境管理• 使用 .env 文件或配置中心(如 Consul、Apollo)按环境(dev/staging/prod)隔离配置。• CI/CD 流水线(如 GitLab CI、Jenkins)通过环境变量、分支或标签触发对应环境的构建与部署。2. Docker 集成• 每个微服务构建为独立的 Docker 镜像,打上版本号与环境标签(如 app:1.0.0-staging)。• 镜像仓库(Harbor、Docker Hub)存储所有版本。• 容器编排层(Kubernetes 或 Docker Swarm)负责调度与服务发现。3. 蓝绿部署• 维护两套完全独立的生产环境:蓝(当前运行)与绿(新版本)。• 部署新版本至绿环境,执行冒烟测试与预检。• 切换流量:通过负载均衡器(Nginx、ALB、K8s Service)将全部流量从蓝切到绿。• 保留蓝环境用于快速回滚(切换回原负载均衡规则)。4. 数据库与有状态服务处理• 采用向后兼容的数据库迁移(如增量脚本),确保蓝绿环境共享同一数据层linux操作系统下载,或对绿环境克隆数据并暂停写入。• 消息队列、缓存等通过消费者组或热备方式平滑过渡。5. 自动化流水线示例• 代码推送 → 单元测试 → 构建 Docker 镜像 → 推送到仓库 → 部署到目标环境(绿)→ 执行健康检查 → 切换负载均衡 → 监控。整体架构1. 目录结构

deploy/
├── deploy.sh                # 主部署脚本
├── docker-compose.blue.yml  # 蓝色环境 compose 文件
├── docker-compose.green.yml # 绿色环境 compose 文件
├── nginx/
│   └── upstream.conf        # Nginx 动态上游配置
├── .env.production
├── .env.staging
└── .env.development

2. 环境配置文件示例(.env.production)

# 通用配置
APP_NAME=myapp
APP_PORT=3000
DB_HOST=prod-db.example.com
DB_PASSWORD=securepassword
 
# 蓝绿部署相关
ACTIVE_COLOR=blue   # 当前活跃颜色(blue 或 green)
NGINX_UPSTREAM_CONF=/etc/nginx/conf.d/upstream.conf

3. Nginx 动态上游配置(nginx/upstream.conf.template)

# 这个文件会被部署脚本动态更新
upstream app_backend {
    server 127.0.0.1:3001;   # 蓝色实例端口
    # server 127.0.0.1:3002;   # 绿色实例端口
}
server {
    listen 80;
    server_name myapp.example.com;
    location / {
        proxy_pass http://app_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

swarm2k docker界面_微服务持续交付Docker蓝绿部署脚本_多环境Docker集成蓝绿部署方案

部署脚本会替换端口并重载 Nginx。

4. 蓝绿部署脚本:deploy.sh功能

#!/bin/bash
# ==================================================
# 蓝绿部署 + Docker + 多环境 脚本
# 用法: ./deploy.sh -e production -v v1.2.3
# ==================================================
set -euo pipefail
# ---------- 默认值 ----------
ENV="production"
IMAGE_VERSION="latest"
ROLLBACK=false
# ---------- 解析参数 ----------
while getopts "e:v:r" opt; do
    case $opt in
        e) ENV="$OPTARG" ;;
        v) IMAGE_VERSION="$OPTARG" ;;
        r) ROLLBACK=true ;;
        *) echo "用法: $0 [-e env] [-v version] [-r]"; exit 1 ;;
    esac
done
# ---------- 加载环境配置 ----------
ENV_FILE=".env.${ENV}"
if [[ ! -f "$ENV_FILE" ]]; then
    echo "错误: 环境文件 $ENV_FILE 不存在"
    exit 1
fi
source "$ENV_FILE"
# ---------- 颜色定义 ----------
COLOR_BLUE="blue"
COLOR_GREEN="green"
# 获取当前活跃颜色(从文件或环境变量)
ACTIVE_COLOR_FILE="/tmp/deploy_active_color_${APP_NAME}"
if [[ -f "$ACTIVE_COLOR_FILE" ]]; then
    ACTIVE_COLOR=$(cat "$ACTIVE_COLOR_FILE")
else
    ACTIVE_COLOR="${ACTIVE_COLOR:-blue}"  # 默认蓝色
fi
if [[ "$ACTIVE_COLOR" == "$COLOR_BLUE" ]]; then
    NEW_COLOR="$COLOR_GREEN"
    OLD_COLOR="$COLOR_BLUE"
    NEW_PORT=3002   # 绿色端口
    OLD_PORT=3001   # 蓝色端口
else
    NEW_COLOR="$COLOR_BLUE"
    OLD_COLOR="$COLOR_GREEN"
    NEW_PORT=3001
    OLD_PORT=3002
fi
echo "当前活跃环境: $ACTIVE_COLOR (端口 $OLD_PORT)"
echo "将部署新版本到: $NEW_COLOR (端口 $NEW_PORT)"
# ---------- 函数:健康检查 ----------
health_check() {
    local port=$1
    local max_retries=30
    local retry=0
    echo "等待服务启动 (端口 $port)..."
    until curl -s -f "http://localhost:${port}/health" > /dev/null; do
        retry=$((retry+1))
        if [[ $retry -ge $max_retries ]]; then
            echo "健康检查失败,服务未就绪"
            return 1
        fi
        sleep 2
    done
    echo "健康检查通过"
    return 0
}
# ---------- 函数:切换 Nginx 上游 ----------
switch_nginx() {
    local new_port=$1
    local old_port=$2
    local upstream_conf="${NGINX_UPSTREAM_CONF:-/etc/nginx/conf.d/upstream.conf}"
    echo "更新 Nginx 配置,将流量切换到端口 $new_port"
    sed -i "s/server 127.0.0.1:$old_port;/server 127.0.0.1:$new_port; # managed by deploy/" "$upstream_conf"
    nginx -t && systemctl reload nginx
    echo "Nginx 已重载,流量已切换"
}
# ---------- 部署新版本 ----------
deploy_new() {
    local color=$1
    local port=$2
    local compose_file="docker-compose.${color}.yml"
    # 准备 compose 文件(替换端口和版本)
    cp "docker-compose.template.yml" "$compose_file"
    sed -i "s/__PORT__/$port/g" "$compose_file"
    sed -i "s/__IMAGE_VERSION__/$IMAGE_VERSION/g" "$compose_file"
    sed -i "s/__ENV__/$ENV/g" "$compose_file"
    echo "启动新版本容器 ($color) ..."
    docker-compose -f "$compose_file" up -d --remove-orphans
    # 健康检查
    if health_check "$port"; then
        echo "新版本部署成功"
        return 0
    else
        echo "新版本健康检查失败,执行回滚"
        docker-compose -f "$compose_file" down
        return 1
    fi
}
# ---------- 清理旧版本 ----------
cleanup_old() {
    local color=$1
    local compose_file="docker-compose.${color}.yml"
    echo "停止并移除旧版本容器 ($color)"
    docker-compose -f "$compose_file" down
}
# ---------- 主流程 ----------
if [[ "$ROLLBACK" == true ]]; then
    echo "执行回滚操作:切换回 $OLD_COLOR"
    switch_nginx "$OLD_PORT" "$NEW_PORT"
    echo "$OLD_COLOR" > "$ACTIVE_COLOR_FILE"
    exit 0
fi
# 正常部署流程
if deploy_new "$NEW_COLOR" "$NEW_PORT"; then
    # 切换流量
    switch_nginx "$NEW_PORT" "$OLD_PORT"
    # 记录新活跃颜色
    echo "$NEW_COLOR" > "$ACTIVE_COLOR_FILE"
    # 清理旧版本(可选延迟清理,保留用于紧急回滚)
    # cleanup_old "$OLD_COLOR"
    echo "蓝绿部署完成,当前活跃: $NEW_COLOR"
else
    echo "部署失败,未切换流量,服务仍使用 $OLD_COLOR"
    exit 1
fi

5. Docker Compose 模板(docker-compose.template.yml)

version: '3.8'
services:
  app:
    image: yourregistry.com/myapp:__IMAGE_VERSION__
    ports:
      - "__PORT__:3000"
    environment:
      - NODE_ENV=__ENV__
      - DB_HOST=${DB_HOST}
      - DB_PASSWORD=${DB_PASSWORD}
    env_file:
      - .env.__ENV__
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

6. 使用步骤6.1 初始化环境

# 创建环境配置文件
cp .env.example .env.production
vim .env.production   # 填写真实配置
# 准备 Nginx 上游配置(手动创建一次)
cat > /etc/nginx/conf.d/upstream.conf <<EOF
upstream app_backend {
    server 127.0.0.1:3001;   # 蓝色初始
}
server {
    listen 80;
    server_name myapp.example.com;
    location / {
        proxy_pass http://app_backend;
    }
}
EOF
nginx -t && systemctl reload nginx

6.2 首次部署(蓝色)

# 假设镜像版本 v1.0.0
./deploy.sh -e production -v v1.0.0
# 自动启动蓝色容器,端口 3001,Nginx 指向它

6.3 升级到新版本(蓝→绿)

./deploy.sh -e production -v v1.1.0
# 脚本会启动绿色容器(端口3002),健康检查通过后切换Nginx,旧蓝色仍在运行但无流量

6.4 回滚到上一个版本

./deploy.sh -e production -r
# 切换 Nginx 回到旧端口,无需重启容器

6.5 彻底清理旧版本

微服务持续交付Docker蓝绿部署脚本_多环境Docker集成蓝绿部署方案_swarm2k docker界面

部署成功后swarm2k docker界面,旧版本容器还在(方便快速回滚)。确认新版本稳定后redflag linux,手动清理:

# 查看当前活跃颜色
cat /tmp/deploy_active_color_myapp   # 输出 green
# 清理蓝色容器
docker-compose -f docker-compose.blue.yml down

7. 进阶增强7.1 集成 Git 版本与镜像构建

在部署脚本开头添加:

# 如果未指定版本,从 Git commit 生成
if [[ "$IMAGE_VERSION" == "latest" ]]; then
    IMAGE_VERSION=$(git rev-parse --short HEAD)
fi
 
# 可选:构建镜像(如果本地需要构建)
docker build -t yourregistry.com/myapp:$IMAGE_VERSION .
docker push yourregistry.com/myapp:$IMAGE_VERSION

7.2 数据库迁移处理

微服务持续交付Docker蓝绿部署脚本_swarm2k docker界面_多环境Docker集成蓝绿部署方案

蓝绿部署时数据库 schema 变更可能导致新旧版本不兼容。推荐:

docker run --rm --network host yourregistry.com/myapp:$IMAGE_VERSION npm run migrate

7.3 使用 Kubernetes 实现蓝绿(更现代)

如果集群已使用 K8s,可通过修改 Service 的 selector 实现蓝绿,无需脚本管理端口。但上述 Docker Compose + Nginx 方案更轻量,适合单机或小规模部署。

8. 总结

特性

实现方式

多环境

.env.{env}

文件 + 命令行参数 -e

Docker 集成

微服务持续交付Docker蓝绿部署脚本_swarm2k docker界面_多环境Docker集成蓝绿部署方案

Docker Compose 模板,通过环境变量注入配置

蓝绿部署

双套 Compose 文件,通过 Nginx 动态切换端口

健康检查

微服务持续交付Docker蓝绿部署脚本_多环境Docker集成蓝绿部署方案_swarm2k docker界面

curl 探测 /health 端点

回滚

一键切回旧端口,旧容器保持运行

这套脚本可直接用于生产swarm2k docker界面,只需根据你的应用调整健康检查路径、端口、镜像仓库地址。

Tagged:
Author

这篇优质的内容由TA贡献而来

刘遄

《Linux就该这么学》书籍作者,RHCA认证架构师,教育学(计算机专业硕士)。

发表回复