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.
 
 
 
 
 
 

156 lines
8.2 KiB

#!/usr/bin/env bash
# admin 开发环境:构建开发镜像 → 推送 → 远端拉取重启。
#
# Nuxt 管理前端打成镜像 yunyan-admin,推到私有仓库后远端拉取重启。
# 仅做镜像部署:服务器上的 docker-compose.yml / .env 由你自行维护
# (照着仓库里的 env/env.example 在服务器上放好真实 .env),本脚本不上传任何真实配置。
#
# 用法(在 deploy/admin/ 下):
# ./dev-deploy.sh lingpu # 发布到灵谱测试环境
# ./dev-deploy.sh yunyan # 发布到云雁测试环境
# ./dev-deploy.sh along # 发布到阿龙测试环境
# ./dev-deploy.sh # 不带参数 → 交互选择环境(无 TTY 时用默认环境 lingpu)
#
# 开发版镜像始终使用固定 tag dev-latest,每次构建覆盖同一 tag。
set -euo pipefail
SVC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # deploy/admin
REPO_ROOT="$(cd "$SVC_DIR/../.." && pwd)" # 仓库根
BUILD_CONTEXT="$REPO_ROOT/apps/admin" # Nuxt 构建上下文
DOCKERFILE="$BUILD_CONTEXT/Dockerfile"
# 各公司镜像仓库地址/账号统一放这里,换仓库只改 deploy/registry-profiles.sh
source "$REPO_ROOT/deploy/registry-profiles.sh"
blue() { printf "\033[34m%s\033[0m\n" "$*"; }
green() { printf "\033[32m%s\033[0m\n" "$*"; }
red() { printf "\033[31m%s\033[0m\n" "$*"; }
IMAGE_NAME="starpivot-admin" # 业务镜像名
# ╔══════════════════════════════════════════════════════════════════════╗
# ║ 各测试环境部署目标 / 私有仓库凭据 —— 每环境一整套 仓库/HOST/KEY/远端目录。 ║
# ║ 写死在此(本文件纳入 git,私有仓库内可接受)。 ║
# ║ ⚠️ 公开仓库前务必清空 DEV_HOST / REGISTRY_PASS ║
# ║ 新增环境:在 env_profile 加一段 case,并把环境名加进 ENVS 数组。 ║
# ╚══════════════════════════════════════════════════════════════════════╝
ENVS=(lingpu yunyan along) # 可选测试环境(交互菜单按此顺序展示)
DEFAULT_ENV="lingpu" # 无参数且无 TTY(CI/管道)时的默认环境
env_profile() {
DEV_PORT=22 # 各环境通用默认
DEV_USER=root
case "$DEV_ENV" in
lingpu)
ENV_DESC="灵谱测试环境 · 香港阿里云 (lingpu-hk)"
registry_profile lingpu # 镜像仓库:灵谱
DEV_HOST="8.217.193.140" # ← 灵谱测试服务器 IP
DEV_KEY=/Users/liwei/Documents/灵谱/lingpu-hk.pem # 本机访问该服务器的 SSH 私钥
DEV_DIR="/home/work/starpivot/admin" # 远端部署目录(其中 docker-compose.yml/.env 由你自己维护)
;;
yunyan)
ENV_DESC="云雁测试环境 · 广州阿里云"
registry_profile yunyan # 镜像仓库:云雁(registry.voitrans.net,就在这台机上)
DEV_HOST="8.138.86.223" # ← 云雁测试服务器 IP(2026-07 由腾讯云 124.222.232.218 迁来)
DEV_KEY=~/.ssh/aliyun_guangzhou.pem # 本机访问该服务器的 SSH 私钥
DEV_DIR="/home/work/starpivot/admin"
;;
along)
ENV_DESC="阿龙测试环境 · 阿里云"
registry_profile along # 镜像仓库:就在这台机上(ym-registry.voitrans.net,账号 admin)
DEV_HOST="8.133.166.29" # ← 阿龙测试服务器 IP
DEV_KEY=~/.ssh/along.pem # 原件在 ~/Documents/阿龙/loginscre.pem,因 macOS TCC 挡文稿目录已拷贝到 ~/.ssh
DEV_DIR="/home/work/starpivot/admin"
;;
*) red "✗ 未知环境: ${DEV_ENV}(应为 ${ENVS[*]// /|})"; exit 1 ;;
esac
}
# 取某环境的目标主机(供交互菜单展示):子 shell 里跑,不污染当前环境变量
env_host_of() { ( DEV_ENV="$1" env_profile >/dev/null 2>&1; printf '%s' "${DEV_HOST:-}" ); }
usage() {
cat >&2 <<EOF
用法: ./dev-deploy.sh [环境] (在 deploy/admin/ 下运行)
环境 : ${ENVS[*]// /, }(省略则交互选择;无 TTY 时用默认 ${DEFAULT_ENV})
例:
./dev-deploy.sh lingpu # 发布到灵谱测试环境
./dev-deploy.sh yunyan # 发布到云雁测试环境
./dev-deploy.sh along # 发布到阿龙测试环境
EOF
}
# ── 参数解析:环境(缺省 → 交互选择)──
case "${1:-}" in -h|--help|help) usage; exit 0 ;; esac
DEV_ENV="${1:-}"
if [ -z "$DEV_ENV" ]; then
if [ -t 0 ]; then
blue "选择要发布的测试环境:"
i=1
for e in "${ENVS[@]}"; do
h="$(env_host_of "$e")"
printf " %d) %-8s → %s\n" "$i" "$e" "${h:-(未配置 IP,需先在脚本 env_profile 填)}" >&2
i=$((i+1))
done
printf " 请输入序号 [1-%d]: " "${#ENVS[@]}" >&2
read -r sel || { red "✗ 已取消"; exit 1; }
case "$sel" in ''|*[!0-9]*) red "✗ 无效序号: $sel"; exit 1 ;; esac
{ [ "$sel" -ge 1 ] && [ "$sel" -le "${#ENVS[@]}" ]; } || { red "✗ 序号超出范围"; exit 1; }
DEV_ENV="${ENVS[$((sel-1))]}"
else
DEV_ENV="$DEFAULT_ENV"
fi
fi
env_profile
green "✓ 目标环境: ${DEV_ENV}(${ENV_DESC})"
PLATFORM="${PLATFORM:-linux/amd64}"
TAG="dev-latest" # 开发版固定 tag,每次构建覆盖同一 dev-latest
FULL_IMAGE="$REGISTRY/$IMAGE_NAME:$TAG"
[ -f "$DOCKERFILE" ] || { red "✗ 缺少 $DOCKERFILE"; exit 1; }
: "${DEV_HOST:?请在 dev-deploy.sh 的 env_profile 中为环境 $DEV_ENV 填 DEV_HOST(服务器 IP)}"
# ── 远程 SSH ──
_ssh() { ssh -p "$DEV_PORT" -i "${DEV_KEY/#\~/$HOME}" -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new "$DEV_USER@$DEV_HOST" "$@"; }
_scp() { scp -P "$DEV_PORT" -i "${DEV_KEY/#\~/$HOME}" -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new "$@"; }
_dest() { echo "$DEV_USER@$DEV_HOST:$1"; }
# 1) 构建并推送镜像
blue ">>> 构建镜像 $FULL_IMAGE (context=$BUILD_CONTEXT)"
echo "$REGISTRY_PASS" | docker login "$REGISTRY" -u "$REGISTRY_USER" --password-stdin
docker build --network=host --platform "$PLATFORM" -f "$DOCKERFILE" -t "$FULL_IMAGE" "$BUILD_CONTEXT"
docker push "$FULL_IMAGE"
# 2) 同步「模板 + compose」到服务器(只传模板,绝不覆盖你维护的真实 .env)
blue ">>> 同步模板与 compose → $DEV_USER@$DEV_HOST:$DEV_DIR"
_ssh "mkdir -p '$DEV_DIR'"
_scp "$SVC_DIR/docker-compose.yml" "$(_dest "$DEV_DIR/docker-compose.yml")"
_scp "$SVC_DIR/env/env.example" "$(_dest "$DEV_DIR/env.example")"
# 3) 远端拉取并重启(用你在服务器维护的真实 .env)
blue ">>> 远端拉取并重启"
_ssh "echo '$REGISTRY_PASS' | docker login '$REGISTRY' -u '$REGISTRY_USER' --password-stdin >/dev/null"
_ssh "docker network inspect 1panel-network >/dev/null 2>&1 || docker network create 1panel-network"
_ssh "if [ -f '$DEV_DIR/.env' ]; then
if grep -q '^CONSOLE_BACKEND=' '$DEV_DIR/.env'; then
sed -i.bak 's#^CONSOLE_BACKEND=.*#CONSOLE_BACKEND=http://starpivot-console:8080#' '$DEV_DIR/.env'
else
echo 'CONSOLE_BACKEND=http://starpivot-console:8080' >> '$DEV_DIR/.env'
fi
else
cp '$DEV_DIR/env.example' '$DEV_DIR/.env' 2>/dev/null || true
fi"
if ! _ssh "test -f '$DEV_DIR/.env'"; then
red "⚠ 服务器缺少真实 .env —— 模板已同步,请登录服务器按模板填好后重跑本脚本:"
echo " ssh -i $DEV_KEY $DEV_USER@$DEV_HOST"
echo " cd $DEV_DIR && cp env.example .env # 编辑 .env 填真实值,然后重跑 ./dev-deploy.sh"
exit 0
fi
# 自动适配 compose 版本 + 去掉 --env-file(老版本/ v1 不认);.env 同目录会自动加载。
_ssh "cd '$DEV_DIR' \
&& if docker compose version >/dev/null 2>&1; then DC='docker compose'; else DC='docker-compose'; fi \
&& REGISTRY='$REGISTRY' TAG='$TAG' \$DC pull \
&& REGISTRY='$REGISTRY' TAG='$TAG' \$DC up -d --force-recreate \
&& docker image prune -f"
green "✓ admin dev[$DEV_ENV] 已发布: $FULL_IMAGE → $DEV_HOST:$DEV_DIR"