Browse Source
云雁(yunyan)/灵谱(lingpu) 的部署目标从所有脚本移除,ENVS / PROD_ENVS / REGIONS
现在都只剩 along。那 6 台(云雁测试/上海/日本/新加坡、灵谱测试/正式)的 SSH 私钥路径
指向的是另一台开发机,本机一台都登不上(22 端口通、无可用密钥),留在交互菜单里只会误选。
- 删 deploy/{console,admin,app}/dev-deploy.sh 的 lingpu、yunyan 两段 env_profile
- 删 deploy/{console,admin}/prod-deploy.sh 的 yunyan、lingpu 两段
- 删 deploy/app/prod-deploy.sh 的 shanghai/japan/singapore 三段 region_profile
- 删 deploy/admin/deploy.sh:早期脚本,只指向灵谱且生产位留空,已被
dev-deploy/prod-deploy 取代(CLAUDE.md 里"要同步两份 deploy.sh"也是错的,
console 那份早就不存在)
- IP 与私钥路径不再记在文档里,需要时从 git 历史取回
镜像仓库刻意保留:registry.voitrans.net / registry.lingpu.net 都在,prod-build.sh
仍可选 yunyan|lingpu 推镜像(三家仓库本机都能读写,协作者仍从他那台机部署这两家)。
顺带修掉三处把已下线机器地址连明文数据库密码一起写死的测试:
- sys/nats/nats_test.go 有个真 bug——`url := "nats://<写死地址>"` 紧接着 `if url == ""`,
常量永远不为空,所谓"默认跳过"从来没生效:每次 go test 都在连那台早已废弃的机器,
白等 4.5 秒超时。现在真正读 NATS_URL 了。
- modules/{api,echomeet}/model_test.go 的 DSN 改走 API_TEST_DSN / ECHOMEET_TEST_DSN
另外给 app/prod-deploy.sh 加了一条明确报错:输入已移除的区域名(如 shanghai)原本会被
is_tag_like 当成版本号,报出"版本指定了两次"这种驴唇不对马嘴的错。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
main
18 changed files with 138 additions and 426 deletions
@ -1,184 +0,0 @@ |
|||||
#!/usr/bin/env bash |
|
||||
# <服务> 部署脚本(每个服务目录各一份,服务名取自所在目录名) |
|
||||
# |
|
||||
# 用法: ./deploy.sh <env> [action] (在 deploy/<服务>/ 下运行) |
|
||||
# env : local | dev | prod |
|
||||
# action : dev/prod → deploy(默认) | up | build | pull | down | restart | logs | ps |
|
||||
# local → up(默认) | build | pull | down | restart | logs | ps |
|
||||
# |
|
||||
# deploy = 构建推送镜像 + 同步配置 + 远程 pull + up(一键发布,仅 dev/prod) |
|
||||
# up = 远程:仅同步配置 + 远程 pull + up(用已推送镜像);本机:起容器 |
|
||||
# |
|
||||
# 例(在 deploy/console/ 下): |
|
||||
# ./deploy.sh prod # 一键发布生产 console |
|
||||
# ./deploy.sh prod logs # 看生产 console 日志 |
|
||||
# ./deploy.sh local up # 本机起 console |
|
||||
# ./deploy.sh dev build # 只构建推送 dev 镜像 |
|
||||
set -euo pipefail |
|
||||
|
|
||||
SVC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # 本服务部署目录(deploy/<服务>) |
|
||||
SERVICE="$(basename "$SVC_DIR")" # 服务名 = 目录名(console / admin) |
|
||||
REPO_ROOT="$(cd "$SVC_DIR/../.." && pwd)" # 仓库根(deploy/<服务>/../..) |
|
||||
|
|
||||
blue() { printf "\033[34m%s\033[0m\n" "$*"; } |
|
||||
green() { printf "\033[32m%s\033[0m\n" "$*"; } |
|
||||
red() { printf "\033[31m%s\033[0m\n" "$*"; } |
|
||||
|
|
||||
# ╔══════════════════════════════════════════════════════════════════════╗ |
|
||||
# ║ 部署目标 / 私有仓库配置 —— 写死在这里,改这里即可(按环境) ║ |
|
||||
# ║ console、admin 同机不同目录;DEPLOY_DIR 自动 = /opt/yunyan/<服务名> ║ |
|
||||
# ║ 注意:本文件纳入 git,下面的密码/IP 会随仓库提交(私有仓库内可接受) ║ |
|
||||
# ╚══════════════════════════════════════════════════════════════════════╝ |
|
||||
deploy_profile() { |
|
||||
DEPLOY_HOST=""; REGISTRY_PASS="" # 占位,local 用不到;dev/prod 在下面填 |
|
||||
# —— 各环境通用默认 —— |
|
||||
REGISTRY=registry.voitrans.net # 私有镜像仓库地址 |
|
||||
REGISTRY_USER=liwei # 仓库账号 |
|
||||
DEPLOY_PORT=22 # 服务器 SSH 端口 |
|
||||
DEPLOY_USER=root # 服务器 SSH 用户 |
|
||||
DEPLOY_KEY=~/Documents/灵谱/lingpu-hk.pem # 本机访问服务器的 SSH 私钥路径 |
|
||||
case "$ENV_NAME" in |
|
||||
dev) |
|
||||
DEPLOY_HOST="8.217.193.140" # 灵谱香港阿里云(lingpu-hk) |
|
||||
REGISTRY_PASS="li13451234" # 私有仓库密码(liwei 用户) |
|
||||
;; |
|
||||
prod) |
|
||||
DEPLOY_HOST="" # ← 生产服务器 IP(必填) |
|
||||
REGISTRY_PASS="" # ← 私有仓库密码(必填) |
|
||||
;; |
|
||||
local) ;; # 本机不走 SSH,无需填 |
|
||||
esac |
|
||||
DEPLOY_DIR="/home/work/starpivot-$SERVICE" # 远程部署目录(与 /home/work 下其余服务一致) |
|
||||
} |
|
||||
|
|
||||
usage() { |
|
||||
cat >&2 <<EOF |
|
||||
用法: ./deploy.sh <env> [action] (在 deploy/$SERVICE/ 下运行) |
|
||||
env : local | dev | prod |
|
||||
action : dev/prod → deploy(默认) | up | build | pull | down | restart | logs | ps |
|
||||
local → up(默认) | build | pull | down | restart | logs | ps |
|
||||
例: |
|
||||
./deploy.sh prod # 一键发布生产 $SERVICE |
|
||||
./deploy.sh prod logs # 看生产 $SERVICE 日志 |
|
||||
./deploy.sh local up # 本机起 $SERVICE |
|
||||
./deploy.sh dev build # 只构建推送 dev 镜像 |
|
||||
EOF |
|
||||
exit 1 |
|
||||
} |
|
||||
|
|
||||
# ── 参数解析与校验 ── |
|
||||
ENV_NAME="${1:-}"; ACTION="${2:-}" |
|
||||
[ -n "$ENV_NAME" ] || usage |
|
||||
[ -f "$SVC_DIR/docker-compose.yml" ] || { red "✗ $SERVICE 目录缺 docker-compose.yml(deploy.sh 须放在服务目录内)"; exit 1; } |
|
||||
case "$ENV_NAME" in |
|
||||
local|dev|prod) ;; |
|
||||
*) red "✗ 未知环境: ${ENV_NAME}(应为 local|dev|prod)"; usage ;; |
|
||||
esac |
|
||||
# 默认动作:远程发布默认 deploy,本机默认 up |
|
||||
[ -n "$ACTION" ] || { [ "$ENV_NAME" = local ] && ACTION=up || ACTION=deploy; } |
|
||||
|
|
||||
# 从 ENV_FILE 安全读取单个变量值(去除可能的外层双引号) |
|
||||
_envget() { |
|
||||
{ grep -E "^$1=" "$ENV_FILE" || true; } | head -1 | cut -d= -f2- | sed -e 's/^"//' -e 's/"$//' |
|
||||
} |
|
||||
|
|
||||
# 载入 env/<环境>.env —— 现在只放容器运行时配置(DSN / Redis / NATS / 密钥 / 端口 / TAG / 网络)。 |
|
||||
# 部署目标与仓库凭据已写死在 deploy_profile,不再放 env 文件。脚本只需从这里取 compose 仍要的 TAG/网络。 |
|
||||
load_env() { |
|
||||
ENV_FILE="$SVC_DIR/env/$ENV_NAME.env" |
|
||||
if [ ! -f "$ENV_FILE" ]; then |
|
||||
red "✗ 缺少 $SERVICE/env/$ENV_NAME.env —— 请先从 $SERVICE/env/$ENV_NAME.env.example 复制并填写" |
|
||||
exit 1 |
|
||||
fi |
|
||||
TAG="$(_envget TAG)"; TAG="${TAG:-latest}" |
|
||||
DOCKER_NETWORK="$(_envget DOCKER_NETWORK)"; DOCKER_NETWORK="${DOCKER_NETWORK:-1panel-network}" |
|
||||
} |
|
||||
|
|
||||
# 生成 compose 用 .env = 服务运行时 env 文件 + 注入写死的 REGISTRY(镜像地址替换用) |
|
||||
# 先滤掉源文件里可能残留的 REGISTRY 行,保证唯一、不依赖 compose 的覆盖顺序。 |
|
||||
gen_env() { |
|
||||
{ grep -v '^REGISTRY=' "$ENV_FILE" || true; } > "$SVC_DIR/.env" |
|
||||
printf 'REGISTRY=%s\n' "$REGISTRY" >> "$SVC_DIR/.env" |
|
||||
} |
|
||||
|
|
||||
# 构建并推送本服务镜像(复用仓库根目录 build.sh,目标 = 服务名)。 |
|
||||
# local 环境只构建不推送(PUSH=0),dev/prod 构建并推送到私有仓库。 |
|
||||
build_push() { |
|
||||
local push=1; [ "$ENV_NAME" = local ] && push=0 |
|
||||
blue ">>> 构建$([ "$push" = 1 ] && echo 推送) $SERVICE 镜像 (TAG=${TAG:-latest}, PUSH=$push)" |
|
||||
TAG="${TAG:-latest}" REGISTRY="$REGISTRY" PUSH="$push" "$REPO_ROOT/build.sh" "$SERVICE" |
|
||||
} |
|
||||
|
|
||||
ensure_network_local() { |
|
||||
docker network inspect "$DOCKER_NETWORK" >/dev/null 2>&1 || docker network create "$DOCKER_NETWORK" |
|
||||
} |
|
||||
|
|
||||
# 本机 docker compose(gen_env 落为同目录 .env,既做变量替换又做容器 env_file) |
|
||||
compose_local() { |
|
||||
gen_env |
|
||||
ensure_network_local |
|
||||
( cd "$SVC_DIR" && docker compose --env-file .env "$@" ) |
|
||||
} |
|
||||
|
|
||||
# ── 远程 SSH 基础 ── |
|
||||
_ssh() { ssh -p "${DEPLOY_PORT:-22}" -i "${DEPLOY_KEY/#\~/$HOME}" -o StrictHostKeyChecking=accept-new "${DEPLOY_USER:-root}@${DEPLOY_HOST}" "$@"; } |
|
||||
_scp() { scp -P "${DEPLOY_PORT:-22}" -i "${DEPLOY_KEY/#\~/$HOME}" -o StrictHostKeyChecking=accept-new "$@"; } |
|
||||
_dest() { echo "${DEPLOY_USER:-root}@${DEPLOY_HOST}:$1"; } |
|
||||
|
|
||||
# 远程发布:同步配置 + 远程 login + pull + up |
|
||||
remote_deploy() { |
|
||||
: "${DEPLOY_HOST:?请在 deploy.sh 顶部 deploy_profile 的 $ENV_NAME 段填 DEPLOY_HOST}" |
|
||||
gen_env |
|
||||
|
|
||||
blue ">>> 同步 $SERVICE 配置到 ${DEPLOY_USER:-root}@${DEPLOY_HOST}:${DEPLOY_DIR}" |
|
||||
_ssh "mkdir -p '$DEPLOY_DIR'" |
|
||||
_scp "$SVC_DIR/docker-compose.yml" "$(_dest "$DEPLOY_DIR/docker-compose.yml")" |
|
||||
_scp "$SVC_DIR/.env" "$(_dest "$DEPLOY_DIR/.env")" |
|
||||
# 带 confs/ 的服务(console)一并同步配置并预建 log 目录 |
|
||||
if [ -d "$SVC_DIR/confs" ]; then |
|
||||
_ssh "mkdir -p '$DEPLOY_DIR/confs' '$DEPLOY_DIR/log'" |
|
||||
_scp -r "$SVC_DIR/confs/." "$(_dest "$DEPLOY_DIR/confs/")" |
|
||||
fi |
|
||||
|
|
||||
blue ">>> 远程拉起 $SERVICE" |
|
||||
[ -n "${REGISTRY_PASS:-}" ] && \ |
|
||||
_ssh "docker login '$REGISTRY' -u '${REGISTRY_USER:-admin}' -p '$REGISTRY_PASS'" |
|
||||
_ssh "docker network inspect '$DOCKER_NETWORK' >/dev/null 2>&1 || docker network create '$DOCKER_NETWORK'" |
|
||||
_ssh "cd '$DEPLOY_DIR' && docker compose --env-file .env pull && docker compose --env-file .env up -d --force-recreate" |
|
||||
} |
|
||||
|
|
||||
# 远程运维(down/restart/logs/ps/pull) |
|
||||
remote_compose() { |
|
||||
: "${DEPLOY_HOST:?请在 deploy.sh 顶部 deploy_profile 的 $ENV_NAME 段填 DEPLOY_HOST}" |
|
||||
_ssh "cd '$DEPLOY_DIR' && docker compose --env-file .env $*" |
|
||||
} |
|
||||
|
|
||||
# ── 分发 ── |
|
||||
deploy_profile # 写死的部署目标 / 仓库凭据 |
|
||||
load_env # env 文件里的运行时配置(TAG / 网络) |
|
||||
|
|
||||
if [ "$ENV_NAME" = local ]; then |
|
||||
case "$ACTION" in |
|
||||
up) compose_local up -d --force-recreate ;; |
|
||||
down) compose_local down ;; |
|
||||
restart) compose_local restart ;; |
|
||||
logs) compose_local logs -f --tail=120 ;; |
|
||||
ps) compose_local ps ;; |
|
||||
pull) compose_local pull ;; |
|
||||
build) build_push ;; |
|
||||
*) red "未知操作: ${ACTION}(local 支持 up|down|restart|logs|ps|pull|build)"; exit 1 ;; |
|
||||
esac |
|
||||
else |
|
||||
case "$ACTION" in |
|
||||
deploy) build_push; remote_deploy ;; |
|
||||
up) remote_deploy ;; |
|
||||
build) build_push ;; |
|
||||
pull) remote_compose pull ;; |
|
||||
down) remote_compose down ;; |
|
||||
restart) remote_compose restart ;; |
|
||||
ps) remote_compose ps ;; |
|
||||
logs) remote_compose logs -f --tail=120 ;; |
|
||||
*) red "未知操作: ${ACTION}(dev/prod 支持 deploy|up|build|pull|down|restart|logs|ps)"; exit 1 ;; |
|
||||
esac |
|
||||
fi |
|
||||
green "✓ $SERVICE $ENV_NAME $ACTION 完成" |
|
||||
Loading…
Reference in new issue