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
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 完成"
|
|
|