208 lines
6.3 KiB
Bash
208 lines
6.3 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
# =============================================================================
|
||
|
|
# 🎁 惊喜 3: 一键部署脚本
|
||
|
|
# =============================================================================
|
||
|
|
# 用途: 一键构建 + 部署整个服务台(开发/生产双模式)
|
||
|
|
# 用法:
|
||
|
|
# bash scripts/oneclick-deploy.sh dev # 本地开发
|
||
|
|
# bash scripts/oneclick-deploy.sh prod # 生产部署
|
||
|
|
# bash scripts/oneclick-deploy.sh prod nas # 生产部署到 NAS
|
||
|
|
# bash scripts/oneclick-deploy.sh prod server # 生产部署到公司服务器
|
||
|
|
# =============================================================================
|
||
|
|
|
||
|
|
set -e
|
||
|
|
|
||
|
|
# 颜色
|
||
|
|
RED='\033[0;31m'
|
||
|
|
GREEN='\033[0;32m'
|
||
|
|
YELLOW='\033[1;33m'
|
||
|
|
BLUE='\033[0;34m'
|
||
|
|
PURPLE='\033[0;35m'
|
||
|
|
NC='\033[0m'
|
||
|
|
|
||
|
|
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||
|
|
ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||
|
|
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
||
|
|
step() { echo -e "\n${PURPLE}━━━ $1 ━━━${NC}"; }
|
||
|
|
|
||
|
|
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||
|
|
cd "$PROJECT_ROOT"
|
||
|
|
|
||
|
|
# 参数
|
||
|
|
MODE="${1:-dev}"
|
||
|
|
TARGET="${2:-local}"
|
||
|
|
|
||
|
|
# =============================================================================
|
||
|
|
# 0. 前置检查
|
||
|
|
# =============================================================================
|
||
|
|
step "0/6 前置检查"
|
||
|
|
|
||
|
|
info "检查 Docker..."
|
||
|
|
if ! command -v docker &> /dev/null; then
|
||
|
|
error "Docker 未安装,请先装 Docker Desktop / Docker Engine"
|
||
|
|
fi
|
||
|
|
ok "Docker: $(docker --version)"
|
||
|
|
|
||
|
|
info "检查 Docker Compose..."
|
||
|
|
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
|
||
|
|
error "Docker Compose 未安装"
|
||
|
|
fi
|
||
|
|
ok "Docker Compose: $(docker compose version 2>/dev/null || docker-compose --version)"
|
||
|
|
|
||
|
|
info "检查磁盘空间..."
|
||
|
|
DISK_FREE=$(df -BG . | tail -1 | awk '{print $4}' | sed 's/G//')
|
||
|
|
if [ "$DISK_FREE" -lt 5 ]; then
|
||
|
|
warn "可用空间 < 5GB,建议清理"
|
||
|
|
fi
|
||
|
|
ok "可用空间: ${DISK_FREE}G"
|
||
|
|
|
||
|
|
# =============================================================================
|
||
|
|
# 1. 环境配置
|
||
|
|
# =============================================================================
|
||
|
|
step "1/6 环境配置"
|
||
|
|
|
||
|
|
case "$MODE" in
|
||
|
|
dev)
|
||
|
|
info "模式: 开发环境"
|
||
|
|
COMPOSE_FILE="docker-compose.yml"
|
||
|
|
ENV_FILE="backend/.env"
|
||
|
|
;;
|
||
|
|
prod)
|
||
|
|
info "模式: 生产环境"
|
||
|
|
COMPOSE_FILE="docker-compose.yml"
|
||
|
|
ENV_FILE="backend/.env"
|
||
|
|
warn "生产部署前请确认 .env 凭据已改"
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
error "未知模式: $MODE (支持: dev / prod)"
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
|
||
|
|
# 加载 .env
|
||
|
|
if [ -f "$ENV_FILE" ]; then
|
||
|
|
set -a
|
||
|
|
# shellcheck disable=SC1090
|
||
|
|
source "$ENV_FILE"
|
||
|
|
set +a
|
||
|
|
ok "已加载: $ENV_FILE"
|
||
|
|
else
|
||
|
|
warn "$ENV_FILE 不存在,用默认"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# =============================================================================
|
||
|
|
# 2. 代码准备
|
||
|
|
# =============================================================================
|
||
|
|
step "2/6 代码准备"
|
||
|
|
|
||
|
|
info "拉取最新代码..."
|
||
|
|
if [ -d .git ]; then
|
||
|
|
git fetch origin 2>/dev/null || warn "无法 fetch(可能离线)"
|
||
|
|
git pull --rebase 2>/dev/null || warn "无法 pull,继续"
|
||
|
|
ok "代码已更新"
|
||
|
|
else
|
||
|
|
warn "非 Git 仓库,跳过"
|
||
|
|
fi
|
||
|
|
|
||
|
|
info "复制环境变量模板..."
|
||
|
|
for env in .env.example backend/.env.example; do
|
||
|
|
if [ -f "$env" ] && [ ! -f "${env%.example}" ]; then
|
||
|
|
cp "$env" "${env%.example}"
|
||
|
|
warn "已复制 $env -> ${env%.example}(请编辑填入真实凭据)"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
# =============================================================================
|
||
|
|
# 3. 镜像构建
|
||
|
|
# =============================================================================
|
||
|
|
step "3/6 镜像构建"
|
||
|
|
|
||
|
|
info "构建 4 个服务镜像..."
|
||
|
|
docker compose -f "$COMPOSE_FILE" build --parallel 2>&1 | tail -30
|
||
|
|
ok "镜像构建完成"
|
||
|
|
|
||
|
|
# =============================================================================
|
||
|
|
# 4. 服务启动
|
||
|
|
# =============================================================================
|
||
|
|
step "4/6 服务启动"
|
||
|
|
|
||
|
|
info "启动服务..."
|
||
|
|
docker compose -f "$COMPOSE_FILE" up -d 2>&1 | tail -20
|
||
|
|
|
||
|
|
# 等待后端 ready
|
||
|
|
info "等待后端就绪..."
|
||
|
|
for i in $(seq 1 30); do
|
||
|
|
if curl -sf http://localhost:8000/health > /dev/null 2>&1; then
|
||
|
|
ok "后端就绪 (用时 ${i}s)"
|
||
|
|
break
|
||
|
|
fi
|
||
|
|
if [ $i -eq 30 ]; then
|
||
|
|
error "后端 30s 内未就绪,跑: docker compose logs backend"
|
||
|
|
fi
|
||
|
|
sleep 1
|
||
|
|
done
|
||
|
|
|
||
|
|
# =============================================================================
|
||
|
|
# 5. 健康验证
|
||
|
|
# =============================================================================
|
||
|
|
step "5/6 健康验证"
|
||
|
|
|
||
|
|
info "检查服务状态..."
|
||
|
|
docker compose -f "$COMPOSE_FILE" ps
|
||
|
|
|
||
|
|
# 6 端检查
|
||
|
|
SERVICES=("backend" "postgres" "redis" "nginx" "frontend-admin" "frontend-agent" "frontend-h5" "frontend-portal")
|
||
|
|
for svc in "${SERVICES[@]}"; do
|
||
|
|
if docker compose -f "$COMPOSE_FILE" ps "$svc" 2>/dev/null | grep -q "Up"; then
|
||
|
|
ok "$svc: 运行中"
|
||
|
|
else
|
||
|
|
warn "$svc: 未运行"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
# 健康端点
|
||
|
|
info "健康端点测试..."
|
||
|
|
HEALTH_URLS=(
|
||
|
|
"http://localhost:8000/health"
|
||
|
|
"http://localhost/itdesk"
|
||
|
|
"http://localhost/itagent"
|
||
|
|
"http://localhost/itadmin"
|
||
|
|
"http://localhost/itportal"
|
||
|
|
)
|
||
|
|
for url in "${HEALTH_URLS[@]}"; do
|
||
|
|
if curl -sf -o /dev/null "$url"; then
|
||
|
|
ok "$url ✅"
|
||
|
|
else
|
||
|
|
warn "$url ❌"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
# =============================================================================
|
||
|
|
# 6. 总结
|
||
|
|
# =============================================================================
|
||
|
|
step "6/6 部署完成"
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "🎉 一键部署完成!"
|
||
|
|
echo ""
|
||
|
|
echo "服务地址:"
|
||
|
|
echo " 📱 H5 员工端: http://localhost/itdesk/"
|
||
|
|
echo " 👤 坐席工作台: http://localhost/itagent/"
|
||
|
|
echo " ⚙️ 管理后台: http://localhost/itadmin/"
|
||
|
|
echo " 🌐 统一入口: http://localhost/itportal/"
|
||
|
|
echo " 🔌 API: http://localhost/api/"
|
||
|
|
echo ""
|
||
|
|
echo "运维命令:"
|
||
|
|
echo " 查看日志: docker compose logs -f [service]"
|
||
|
|
echo " 重启服务: docker compose restart [service]"
|
||
|
|
echo " 停止: docker compose down"
|
||
|
|
echo " 完全清理: docker compose down -v"
|
||
|
|
echo ""
|
||
|
|
echo "后续:"
|
||
|
|
echo " 1. 跑安全审计: bash scripts/security-audit.sh"
|
||
|
|
echo " 2. 跑健康仪表盘: python scripts/dashboard.py"
|
||
|
|
echo " 3. 跑 API 文档: bash scripts/generate-api-docs.sh"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
ok "🎁 一键部署成功"
|