You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

105 lines
5.3 KiB

#!/usr/bin/env bash
# voitrans 生产环境:部署到指定区域(选择区域 + 镜像版本 tag),支持回滚。
#
# 镜像由 ./prod-build.sh 预先构建推送;本脚本只做「同步配置 + 远端拉取 + 重启」。
# 每个区域一套服务器配置(见下方 region_profile)。各区域共用同一镜像 voitrans-a11。
#
# 用法(在 deploy/voitrans/ 下):
# ./prod-deploy.sh <区域> <tag> # 部署指定版本,如 ./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 <shanghai|japan|singapore> <tag|rollback>"; 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 完成"