#!/bin/bash # ============================================================ # OpenDance Studio Web 服务端 —— 一键部署脚本 # # 部署内容:API(NestJS)+ 管理端(静态站点) # 不部署内容:MySQL —— 数据库为部署方提供的现有实例(见 contracts/database.md) # # 用法: # cp .env.example .env && vi .env # ./install.sh # ============================================================ set -euo pipefail cd "$(dirname "$0")" log() { printf '\033[1;34m[install]\033[0m %s\n' "$*"; } warn() { printf '\033[1;33m[warn]\033[0m %s\n' "$*"; } die() { printf '\033[1;31m[error]\033[0m %s\n' "$*" >&2; exit 1; } # ---------- 1. 前置检查 ---------- if [ ! -f .env ]; then die "缺少 .env 文件,请从 .env.example 复制并填写数据库连接信息: cp .env.example .env && vi .env" fi # shellcheck disable=SC1091 set -a; . ./.env; set +a [ -n "${DB_HOST:-}" ] || die ".env 中 DB_HOST 未设置" [ -n "${DB_USER:-}" ] || die ".env 中 DB_USER 未设置" [ -n "${DB_NAME:-}" ] || die ".env 中 DB_NAME 未设置" [ -n "${DB_PASS:-}" ] || die ".env 中 DB_PASS 未设置" if docker compose version >/dev/null 2>&1; then DC="docker compose" elif command -v docker-compose >/dev/null 2>&1; then DC="docker-compose" else die "未找到 docker compose 或 docker-compose,请先安装 Docker" fi command -v docker >/dev/null 2>&1 || die "未找到 docker" log "目标数据库:${DB_HOST}:${DB_PORT:-3306}/${DB_NAME}(现有实例,本脚本不会创建或管理 MySQL)" # ---------- 2. 构建镜像 ---------- log "构建镜像(API + Admin)..." $DC build # ---------- 3. 执行数据库迁移 ---------- # 表结构由 TypeORM migration 创建;DB_SYNCHRONIZE 恒为 false log "执行 TypeORM 迁移..." $DC run --rm api npm run migration:run # ---------- 4. 启动服务 ---------- log "启动服务..." $DC up -d # ---------- 5. 健康检查 ---------- API_PORT="${API_PORT:-3000}" ADMIN_PORT="${ADMIN_PORT:-8080}" HEALTH_URL="http://127.0.0.1:${API_PORT}/health" log "等待 API 健康检查:${HEALTH_URL}" ok=0 for i in $(seq 1 30); do if command -v curl >/dev/null 2>&1; then if curl -fsS -m 3 "$HEALTH_URL" >/dev/null 2>&1; then ok=1; break; fi else if $DC exec -T api node -e "fetch('http://127.0.0.1:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" >/dev/null 2>&1; then ok=1; break fi fi sleep 2 done if [ "$ok" -ne 1 ]; then warn "健康检查未在 60 秒内通过,最近日志:" $DC logs --tail=50 api || true die "部署未通过健康检查" fi if command -v curl >/dev/null 2>&1; then log "健康检查响应:$(curl -fsS -m 5 "$HEALTH_URL")" fi HOST_HINT="${DEPLOY_HOST:-}" cat <