#!/usr/bin/env bash # voitrans 生产环境:部署到指定区域(选择区域 + 镜像版本 tag),支持回滚。 # # 镜像由 ./prod-build.sh 预先构建推送;本脚本只做「同步配置 + 远端拉取 + 重启」。 # 每个区域一套服务器配置(见下方 region_profile)。各区域共用同一镜像 voitrans-a11。 # # 用法(在 deploy/voitrans/ 下): # ./prod-deploy.sh <区域> # 部署指定版本,如 ./prod-deploy.sh shanghai 0.1.1 # ./prod-deploy.sh <区域> rollback # 回滚到上一次部署版本(与当前版本来回切换) # 区域: shanghai | japan | singapore set -euo pipefail SVC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" blue() { printf "\033[34m%s\033[0m\n" "$*"; } green() { printf "\033[32m%s\033[0m\n" "$*"; } red() { printf "\033[31m%s\033[0m\n" "$*"; } # ── 私有仓库凭据(写死;公开仓库前清空 REGISTRY_PASS)── IMAGE_NAME="voitrans-a11" REGISTRY="docker-registry.ideapsound.com" REGISTRY_USER="admin" REGISTRY_PASS="li13451234" # ╔══════════════════════════════════════════════════════════════════════╗ # ║ 各区域部署目标 —— 写死在此(本文件纳入 git)。公开仓库前清空 HOST。 ║ # ║ 新增区域:在此加一段 case + 在 env/ 下加 <区域>.env ║ # ╚══════════════════════════════════════════════════════════════════════╝ region_profile() { DEPLOY_PORT=22 DEPLOY_USER=root DEPLOY_KEY=~/.ssh/id_rsa DEPLOY_DIR="/opt/yunyan/voitrans" # 远端部署目录(各区域机器各一份) case "$REGION" in shanghai) DEPLOY_HOST="" ;; # ← 上海生产服务器 IP(必填) japan) DEPLOY_HOST="" ;; # ← 日本生产服务器 IP(必填) singapore) DEPLOY_HOST="" ;; # ← 新加坡生产服务器 IP(必填) *) red "✗ 未知区域: $REGION(应为 shanghai|japan|singapore)"; exit 1 ;; esac } # ── 参数 ── REGION="${1:-}"; ARG2="${2:-}" [ -n "$REGION" ] && [ -n "$ARG2" ] || { red "用法: ./prod-deploy.sh "; exit 1; } if [ "$ARG2" = "rollback" ]; then MODE="rollback"; NEW_TAG=""; else MODE="deploy"; NEW_TAG="$ARG2"; fi region_profile : "${DEPLOY_HOST:?请在 prod-deploy.sh 的 region_profile($REGION) 段填 DEPLOY_HOST}" ENV_FILE="$SVC_DIR/env/$REGION.env" [ -f "$ENV_FILE" ] || { red "✗ 缺少 env/$REGION.env"; exit 1; } [ -f "$SVC_DIR/docker-compose.yml" ] || { red "✗ 缺少 docker-compose.yml"; exit 1; } # 取 DOCKER_NETWORK(compose 外部网络名) DOCKER_NETWORK="$({ grep -E '^DOCKER_NETWORK=' "$ENV_FILE" || true; } | head -1 | cut -d= -f2-)" DOCKER_NETWORK="${DOCKER_NETWORK:-1panel-network}" # 生成 .env.infra = <区域>.env(去掉 TAG/PREV_TAG/REGISTRY) + 注入 REGISTRY。TAG/PREV_TAG 由远端管理。 gen_env_infra() { { grep -vE '^(REGISTRY|TAG|PREV_TAG)=' "$ENV_FILE" || true; } > "$SVC_DIR/.env.infra" printf 'REGISTRY=%s\n' "$REGISTRY" >> "$SVC_DIR/.env.infra" } _ssh() { ssh -p "$DEPLOY_PORT" -i "${DEPLOY_KEY/#\~/$HOME}" -o StrictHostKeyChecking=accept-new "$DEPLOY_USER@$DEPLOY_HOST" "$@"; } _scp() { scp -P "$DEPLOY_PORT" -i "${DEPLOY_KEY/#\~/$HOME}" -o StrictHostKeyChecking=accept-new "$@"; } _dest() { echo "$DEPLOY_USER@$DEPLOY_HOST:$1"; } gen_env_infra blue ">>> [$REGION] 同步配置到 $DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_DIR ($MODE${NEW_TAG:+ $NEW_TAG})" _ssh "mkdir -p '$DEPLOY_DIR/confs' '$DEPLOY_DIR/log'" _scp "$SVC_DIR/docker-compose.yml" "$(_dest "$DEPLOY_DIR/docker-compose.yml")" _scp "$SVC_DIR/.env.infra" "$(_dest "$DEPLOY_DIR/.env.infra")" _scp -r "$SVC_DIR/confs/." "$(_dest "$DEPLOY_DIR/confs/")" blue ">>> [$REGION] 远端计算版本、拉取并重启" _ssh bash -s -- "$DEPLOY_DIR" "$MODE" "$NEW_TAG" "$REGISTRY/$IMAGE_NAME" "$REGISTRY" "$REGISTRY_USER" "$REGISTRY_PASS" "$DOCKER_NETWORK" <<'REMOTE' set -e DIR="$1"; MODE="$2"; NEW_TAG="$3"; IMG_PREFIX="$4"; REG="$5"; REG_USER="$6"; REG_PASS="$7"; NET="$8" getline() { [ -f "$DIR/.env" ] && { grep -E "^$1=" "$DIR/.env" 2>/dev/null | tail -1 | cut -d= -f2- || true; } | tr -d '\r'; } CUR_TAG="$(getline TAG)" CUR_PREV="$(getline PREV_TAG)" if [ "$MODE" = "rollback" ]; then [ -n "$CUR_PREV" ] || { echo "没有 PREV_TAG,无法回滚"; exit 1; } FINAL_TAG="$CUR_PREV"; FINAL_PREV="$CUR_TAG" # 与当前版本来回切换 else FINAL_TAG="$NEW_TAG" if [ -n "$CUR_TAG" ] && [ "$CUR_TAG" != "$NEW_TAG" ]; then FINAL_PREV="$CUR_TAG"; else FINAL_PREV="$CUR_PREV"; fi fi # 写新 .env = 同步来的基础设施配置 + PREV_TAG + TAG cp "$DIR/.env.infra" "$DIR/.env" [ -n "$FINAL_PREV" ] && echo "PREV_TAG=$FINAL_PREV" >> "$DIR/.env" echo "TAG=$FINAL_TAG" >> "$DIR/.env" echo "$REG_PASS" | docker login "$REG" -u "$REG_USER" --password-stdin >/dev/null docker network inspect "$NET" >/dev/null 2>&1 || docker network create "$NET" docker pull "$IMG_PREFIX:$FINAL_TAG" cd "$DIR" && docker compose --env-file .env up -d docker image prune -f echo "已部署版本 TAG=$FINAL_TAG (PREV_TAG=${FINAL_PREV:-无})" REMOTE green "✓ voitrans [$REGION] $MODE 完成"