|
@@ -1,56 +1,205 @@
|
|
|
#!/bin/bash
|
|
#!/bin/bash
|
|
|
|
|
+#
|
|
|
|
|
+# math_cms 统一部署脚本
|
|
|
|
|
+#
|
|
|
|
|
+# 用法:
|
|
|
|
|
+# ./deploy.sh # 部署第一台服务器(主站)
|
|
|
|
|
+# ./deploy.sh api # 部署第二台服务器(API)
|
|
|
|
|
+# ./deploy.sh pdf # 部署第三/四台服务器(PDF Worker)
|
|
|
|
|
+# ./deploy.sh all # 部署当前服务器所有服务
|
|
|
|
|
+#
|
|
|
|
|
+# 流程:git pull → 前端构建 → 清 Laravel 缓存 → 重建并重启容器
|
|
|
|
|
+#
|
|
|
|
|
|
|
|
set -e
|
|
set -e
|
|
|
|
|
|
|
|
-echo "🚀 快速部署 Filament Admin"
|
|
|
|
|
|
|
+# ============ 配置 ============
|
|
|
|
|
+COMPOSE_FILES_MAIN="-f docker-compose.yml -f docker-compose.mount.yml"
|
|
|
|
|
+COMPOSE_FILES_API="-f docker-compose.api.yml -f docker-compose.api.mount.yml"
|
|
|
|
|
+COMPOSE_FILES_PDF="-f docker-compose.pdf.yml -f docker-compose.pdf.mount.yml"
|
|
|
|
|
|
|
|
-# 颜色定义
|
|
|
|
|
|
|
+# ============ 颜色 ============
|
|
|
RED='\033[0;31m'
|
|
RED='\033[0;31m'
|
|
|
GREEN='\033[0;32m'
|
|
GREEN='\033[0;32m'
|
|
|
YELLOW='\033[1;33m'
|
|
YELLOW='\033[1;33m'
|
|
|
BLUE='\033[0;34m'
|
|
BLUE='\033[0;34m'
|
|
|
NC='\033[0m'
|
|
NC='\033[0m'
|
|
|
|
|
|
|
|
-# 检查镜像是否存在
|
|
|
|
|
-if ! docker images filamentadmin:latest | grep -q filamentadmin; then
|
|
|
|
|
- echo -e "${RED}❌ 错误:未找到镜像 filamentadmin:latest${NC}"
|
|
|
|
|
- echo -e "${YELLOW}💡 请先运行 ./build.sh 构建镜像${NC}"
|
|
|
|
|
- exit 1
|
|
|
|
|
-fi
|
|
|
|
|
-
|
|
|
|
|
-echo -e "${BLUE}ℹ️ 部署信息:${NC}"
|
|
|
|
|
-echo " 镜像:filamentadmin:latest"
|
|
|
|
|
-echo " 端口:5019:8000"
|
|
|
|
|
-echo " 容器名:filament_admin"
|
|
|
|
|
-echo ""
|
|
|
|
|
-
|
|
|
|
|
-# 停止并删除现有容器
|
|
|
|
|
-if docker ps -a | grep -q filament_admin; then
|
|
|
|
|
- echo -e "${YELLOW}🛑 停止现有容器...${NC}"
|
|
|
|
|
- docker compose down
|
|
|
|
|
-fi
|
|
|
|
|
-
|
|
|
|
|
-# 启动新容器
|
|
|
|
|
-echo -e "${GREEN}▶️ 启动容器...${NC}"
|
|
|
|
|
-docker compose up -d
|
|
|
|
|
-
|
|
|
|
|
-# 等待服务启动
|
|
|
|
|
-echo -e "${YELLOW}⏳ 等待服务启动...${NC}"
|
|
|
|
|
-sleep 5
|
|
|
|
|
-
|
|
|
|
|
-# 检查状态
|
|
|
|
|
-if docker compose ps | grep -q "Up"; then
|
|
|
|
|
- echo -e "${GREEN}✅ 部署成功!${NC}"
|
|
|
|
|
|
|
+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; }
|
|
|
|
|
+
|
|
|
|
|
+# ============ 步骤 1:拉取代码 ============
|
|
|
|
|
+git_pull() {
|
|
|
|
|
+ info "拉取最新代码..."
|
|
|
|
|
+ git fetch origin main
|
|
|
|
|
+ LOCAL=$(git rev-parse HEAD)
|
|
|
|
|
+ REMOTE=$(git rev-parse origin/main)
|
|
|
|
|
+
|
|
|
|
|
+ if [ "$LOCAL" = "$REMOTE" ]; then
|
|
|
|
|
+ ok "代码已是最新 ($LOCAL)"
|
|
|
|
|
+ else
|
|
|
|
|
+ git pull origin main
|
|
|
|
|
+ ok "代码已更新"
|
|
|
|
|
+ fi
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ============ 步骤 2:前端构建 ============
|
|
|
|
|
+build_frontend() {
|
|
|
|
|
+ info "构建前端资源..."
|
|
|
|
|
+
|
|
|
|
|
+ # 检测宿主机是否有 bun/npm
|
|
|
|
|
+ if command -v bun &>/dev/null; then
|
|
|
|
|
+ info "使用 bun 构建..."
|
|
|
|
|
+ bun install
|
|
|
|
|
+ bun run build
|
|
|
|
|
+ elif command -v npm &>/dev/null; then
|
|
|
|
|
+ info "使用 npm 构建..."
|
|
|
|
|
+ npm install --prefer-offline
|
|
|
|
|
+ npm run build
|
|
|
|
|
+ else
|
|
|
|
|
+ # 宿主机没有 Node.js,用 Docker 容器构建
|
|
|
|
|
+ info "宿主机无 Node.js,使用 Docker 容器构建..."
|
|
|
|
|
+ docker run --rm \
|
|
|
|
|
+ -v "$(pwd):/app" \
|
|
|
|
|
+ -w /app \
|
|
|
|
|
+ node:20-alpine \
|
|
|
|
|
+ sh -c "npm config set registry https://registry.npmmirror.com && npm install && npm run build"
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ # 验证构建产物
|
|
|
|
|
+ if [ ! -f "public/build/manifest.json" ]; then
|
|
|
|
|
+ error "前端构建失败:public/build/manifest.json 不存在"
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ ok "前端构建完成"
|
|
|
|
|
+ info "构建产物:"
|
|
|
|
|
+ ls -la public/build/assets/
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ============ 步骤 3:清 Laravel 缓存 ==========
|
|
|
|
|
+clear_cache() {
|
|
|
|
|
+ info "清除 Laravel 缓存..."
|
|
|
|
|
+
|
|
|
|
|
+ # 如果容器正在运行,通过容器执行
|
|
|
|
|
+ if docker ps --format '{{.Names}}' 2>/dev/null | grep -q 'math_cms_app'; then
|
|
|
|
|
+ local container=$(docker ps --format '{{.Names}}' | grep 'math_cms_app' | head -1)
|
|
|
|
|
+ docker exec "$container" php artisan view:clear 2>/dev/null || true
|
|
|
|
|
+ docker exec "$container" php artisan cache:clear 2>/dev/null || true
|
|
|
|
|
+ ok "通过容器清除缓存"
|
|
|
|
|
+ else
|
|
|
|
|
+ # 容器未运行时本地执行(需要 PHP)
|
|
|
|
|
+ php artisan view:clear 2>/dev/null || true
|
|
|
|
|
+ php artisan cache:clear 2>/dev/null || true
|
|
|
|
|
+ ok "本地清除缓存"
|
|
|
|
|
+ fi
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ============ 步骤 4:构建镜像并重启 ============
|
|
|
|
|
+deploy_services() {
|
|
|
|
|
+ local compose_files="$1"
|
|
|
|
|
+ shift
|
|
|
|
|
+ local services="$@"
|
|
|
|
|
+
|
|
|
|
|
+ info "构建 Docker 镜像..."
|
|
|
|
|
+ docker compose $compose_files build --no-cache app
|
|
|
|
|
+
|
|
|
|
|
+ if [ -z "$services" ]; then
|
|
|
|
|
+ services="app"
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ info "重启服务: $services"
|
|
|
|
|
+ docker compose $compose_files up -d --no-deps --force-recreate $services
|
|
|
|
|
+
|
|
|
|
|
+ ok "服务已重启: $services"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ============ 步骤 5:验证 ============
|
|
|
|
|
+verify() {
|
|
|
|
|
+ local compose_files="$1"
|
|
|
|
|
+
|
|
|
|
|
+ info "等待服务启动..."
|
|
|
|
|
+ sleep 5
|
|
|
|
|
+
|
|
|
|
|
+ # 检查容器状态
|
|
|
|
|
+ local status=$(docker compose $compose_files ps --format '{{.Status}}' 2>/dev/null | head -1)
|
|
|
|
|
+ if echo "$status" | grep -q 'Up'; then
|
|
|
|
|
+ ok "容器运行正常 ($status)"
|
|
|
|
|
+ else
|
|
|
|
|
+ warn "容器状态: $status"
|
|
|
|
|
+ warn "请检查日志: docker compose $compose_files logs --tail=50"
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ # 检查前端资源是否可访问
|
|
|
|
|
+ local port=$(docker compose $compose_files port app 8000 2>/dev/null | cut -d: -f2)
|
|
|
|
|
+ if [ -n "$port" ]; then
|
|
|
|
|
+ local manifest_status=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:$port/build/manifest.json" 2>/dev/null || echo "000")
|
|
|
|
|
+ if [ "$manifest_status" = "200" ]; then
|
|
|
|
|
+ ok "前端资源验证通过 (manifest.json HTTP $manifest_status)"
|
|
|
|
|
+ else
|
|
|
|
|
+ warn "前端资源验证失败 (manifest.json HTTP $manifest_status)"
|
|
|
|
|
+ fi
|
|
|
|
|
+ fi
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ============ 主流程 ============
|
|
|
|
|
+main() {
|
|
|
|
|
+ local mode="${1:-main}"
|
|
|
|
|
+
|
|
|
echo ""
|
|
echo ""
|
|
|
- echo -e "${BLUE}🌐 访问地址:${NC}"
|
|
|
|
|
- echo -e " http://localhost:5019/admin"
|
|
|
|
|
|
|
+ echo -e "${BLUE}========================================${NC}"
|
|
|
|
|
+ echo -e "${BLUE} math_cms 部署脚本${NC}"
|
|
|
|
|
+ echo -e "${BLUE}========================================${NC}"
|
|
|
echo ""
|
|
echo ""
|
|
|
- echo -e "${BLUE}📋 常用命令:${NC}"
|
|
|
|
|
- echo -e " 查看日志:${GREEN}docker compose logs -f${NC}"
|
|
|
|
|
- echo -e " 停止服务:${GREEN}docker compose down${NC}"
|
|
|
|
|
- echo -e " 重启服务:${GREEN}docker compose restart${NC}"
|
|
|
|
|
-else
|
|
|
|
|
- echo -e "${RED}❌ 部署失败,请检查日志:${NC}"
|
|
|
|
|
- docker compose logs
|
|
|
|
|
- exit 1
|
|
|
|
|
-fi
|
|
|
|
|
|
|
+
|
|
|
|
|
+ git_pull
|
|
|
|
|
+ build_frontend
|
|
|
|
|
+ clear_cache
|
|
|
|
|
+
|
|
|
|
|
+ case "$mode" in
|
|
|
|
|
+ main|1)
|
|
|
|
|
+ info "部署模式:主站(第一台服务器)"
|
|
|
|
|
+ deploy_services "$COMPOSE_FILES_MAIN" app queue pdf-worker gotenberg
|
|
|
|
|
+ verify "$COMPOSE_FILES_MAIN"
|
|
|
|
|
+ ;;
|
|
|
|
|
+ api|2)
|
|
|
|
|
+ info "部署模式:API(第二台服务器)"
|
|
|
|
|
+ deploy_services "$COMPOSE_FILES_API" app
|
|
|
|
|
+ verify "$COMPOSE_FILES_API"
|
|
|
|
|
+ ;;
|
|
|
|
|
+ pdf|3)
|
|
|
|
|
+ info "部署模式:PDF Worker(第三/四台服务器)"
|
|
|
|
|
+ deploy_services "$COMPOSE_FILES_PDF" app pdf-worker-1 pdf-worker-2 logic-worker-1 logic-worker-2 gotenberg
|
|
|
|
|
+ verify "$COMPOSE_FILES_PDF"
|
|
|
|
|
+ ;;
|
|
|
|
|
+ all)
|
|
|
|
|
+ info "部署模式:所有服务"
|
|
|
|
|
+ # 自动检测当前服务器使用的 compose 文件
|
|
|
|
|
+ if [ -f "docker-compose.pdf.yml" ] && docker ps --format '{{.Names}}' 2>/dev/null | grep -q 'pdf_worker'; then
|
|
|
|
|
+ deploy_services "$COMPOSE_FILES_PDF" app pdf-worker-1 pdf-worker-2 logic-worker-1 logic-worker-2 gotenberg
|
|
|
|
|
+ verify "$COMPOSE_FILES_PDF"
|
|
|
|
|
+ elif docker ps --format '{{.Names}}' 2>/dev/null | grep -q 'math_cms_queue'; then
|
|
|
|
|
+ deploy_services "$COMPOSE_FILES_MAIN" app queue pdf-worker gotenberg
|
|
|
|
|
+ verify "$COMPOSE_FILES_MAIN"
|
|
|
|
|
+ else
|
|
|
|
|
+ deploy_services "$COMPOSE_FILES_API" app
|
|
|
|
|
+ verify "$COMPOSE_FILES_API"
|
|
|
|
|
+ fi
|
|
|
|
|
+ ;;
|
|
|
|
|
+ *)
|
|
|
|
|
+ echo "用法: $0 [main|api|pdf|all]"
|
|
|
|
|
+ echo " main - 第一台服务器(主站,默认)"
|
|
|
|
|
+ echo " api - 第二台服务器(API)"
|
|
|
|
|
+ echo " pdf - 第三/四台服务器(PDF Worker)"
|
|
|
|
|
+ echo " all - 自动检测并部署当前服务器所有服务"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+ ;;
|
|
|
|
|
+ esac
|
|
|
|
|
+
|
|
|
|
|
+ echo ""
|
|
|
|
|
+ ok "部署完成!"
|
|
|
|
|
+ echo ""
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+main "$@"
|