From eae1350f352341fb7f38d8f01c56383ce0055482 Mon Sep 17 00:00:00 2001 From: Developer Date: Tue, 2 Dec 2025 19:34:31 -0800 Subject: [PATCH] =?UTF-8?q?feat(admin-service):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=E7=9A=84=E9=87=8F=E4=BA=A7=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E8=AE=BE=E6=96=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 参考 identity-service 的部署配置,为 admin-service 添加: 新增文件: - .dockerignore: Docker 构建排除配置 - .env.development: 开发环境配置 - .env.production: 生产环境配置(使用变量引用) - docker-compose.yml: 完整的 Docker 编排(含 PostgreSQL, Redis) 更新文件: - deploy.sh: 增强部署脚本,新增 30+ 命令(健康检查、测试、清理等) - docs/DEPLOYMENT.md: 整合快速开始指南和命令速查表 服务架构: - admin-service: 端口 3010 - PostgreSQL: 端口 5433(避免冲突) - Redis: 端口 6380(避免冲突) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- backend/services/admin-service/.dockerignore | 62 +++ .../services/admin-service/.env.development | 21 + .../services/admin-service/.env.production | 23 + backend/services/admin-service/deploy.sh | 296 ++++++++++-- .../services/admin-service/docker-compose.yml | 89 ++++ .../services/admin-service/docs/DEPLOYMENT.md | 448 ++++++++++++------ 6 files changed, 752 insertions(+), 187 deletions(-) create mode 100644 backend/services/admin-service/.dockerignore create mode 100644 backend/services/admin-service/.env.development create mode 100644 backend/services/admin-service/.env.production create mode 100644 backend/services/admin-service/docker-compose.yml diff --git a/backend/services/admin-service/.dockerignore b/backend/services/admin-service/.dockerignore new file mode 100644 index 00000000..2cf6d03b --- /dev/null +++ b/backend/services/admin-service/.dockerignore @@ -0,0 +1,62 @@ +# ============================================================================= +# Admin Service - Docker Ignore File +# ============================================================================= + +# Dependencies (will be installed fresh in container) +node_modules/ + +# Build output (will be built in container) +dist/ + +# Environment files (will be provided at runtime) +.env +.env.local +.env.development +.env.development.local +.env.test +.env.test.local +.env.production +.env.production.local + +# Git +.git/ +.gitignore + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Test +coverage/ +.nyc_output +test/ + +# Logs +logs/ +*.log + +# Docker +Dockerfile +Dockerfile.test +docker-compose.yml +docker-compose.test.yml +.dockerignore + +# Documentation +*.md +docs/ + +# Scripts (not needed in container) +scripts/ + +# Claude +.claude/ + +# Database scripts (mounted separately if needed) +database/ diff --git a/backend/services/admin-service/.env.development b/backend/services/admin-service/.env.development new file mode 100644 index 00000000..a27fbeee --- /dev/null +++ b/backend/services/admin-service/.env.development @@ -0,0 +1,21 @@ +# ============================================================================= +# Admin Service - Development Environment +# ============================================================================= + +# Application +NODE_ENV=development +APP_PORT=3010 +API_PREFIX=api/v1 + +# Database (本地开发) +DATABASE_URL="postgresql://postgres:password@localhost:5432/rwa_admin?schema=public" + +# JWT +JWT_SECRET="dev-admin-jwt-secret-key" +JWT_EXPIRES_IN="7d" + +# Redis (可选,用于缓存) +REDIS_HOST="localhost" +REDIS_PORT=6379 +REDIS_PASSWORD="" +REDIS_DB=9 diff --git a/backend/services/admin-service/.env.production b/backend/services/admin-service/.env.production new file mode 100644 index 00000000..36cd9f8e --- /dev/null +++ b/backend/services/admin-service/.env.production @@ -0,0 +1,23 @@ +# ============================================================================= +# Admin Service - Production Environment +# ============================================================================= +# 注意: 生产环境使用变量引用,实际值在部署时通过环境变量注入 +# ============================================================================= + +# Application +NODE_ENV=production +APP_PORT=3010 +API_PREFIX=api/v1 + +# Database +DATABASE_URL="postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:5432/${DB_NAME}?schema=public" + +# JWT +JWT_SECRET="${JWT_SECRET}" +JWT_EXPIRES_IN="7d" + +# Redis (可选,用于缓存) +REDIS_HOST="${REDIS_HOST}" +REDIS_PORT=6379 +REDIS_PASSWORD="${REDIS_PASSWORD}" +REDIS_DB=9 diff --git a/backend/services/admin-service/deploy.sh b/backend/services/admin-service/deploy.sh index d4331427..3279a415 100644 --- a/backend/services/admin-service/deploy.sh +++ b/backend/services/admin-service/deploy.sh @@ -1,6 +1,8 @@ #!/bin/bash # ============================================================================= -# Admin Service - Individual Deployment Script +# Admin Service - Deployment Script +# ============================================================================= +# 用法: ./deploy.sh # ============================================================================= set -e @@ -9,60 +11,113 @@ SERVICE_NAME="admin-service" CONTAINER_NAME="rwa-admin-service" IMAGE_NAME="services-admin-service" PORT=3010 +HEALTH_ENDPOINT="http://localhost:${PORT}/api/v1/health" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' +CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } +log_step() { echo -e "${CYAN}[STEP]${NC} $1"; } # Get script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SERVICES_DIR="$(dirname "$SCRIPT_DIR")" # Load environment -if [ -f "$SERVICES_DIR/.env" ]; then - export $(cat "$SERVICES_DIR/.env" | grep -v '^#' | xargs) -fi +load_env() { + if [ -f "$SCRIPT_DIR/.env" ]; then + export $(cat "$SCRIPT_DIR/.env" | grep -v '^#' | xargs) + log_info "Loaded .env from $SCRIPT_DIR" + elif [ -f "$SERVICES_DIR/.env" ]; then + export $(cat "$SERVICES_DIR/.env" | grep -v '^#' | xargs) + log_info "Loaded .env from $SERVICES_DIR" + fi +} + +# Show banner +show_banner() { + echo -e "${CYAN}" + echo "╔═══════════════════════════════════════════════════════════════╗" + echo "║ Admin Service Deployment Script ║" + echo "║ Version Management API ║" + echo "╚═══════════════════════════════════════════════════════════════╝" + echo -e "${NC}" +} case "$1" in + # ========================================================================= + # Build Commands + # ========================================================================= build) - log_info "Building $SERVICE_NAME..." + show_banner + log_info "Building $SERVICE_NAME Docker image..." docker build -t "$IMAGE_NAME" "$SCRIPT_DIR" log_success "$SERVICE_NAME built successfully" ;; build-no-cache) + show_banner log_info "Building $SERVICE_NAME (no cache)..." docker build --no-cache -t "$IMAGE_NAME" "$SCRIPT_DIR" - log_success "$SERVICE_NAME built successfully" + log_success "$SERVICE_NAME built successfully (no cache)" ;; + # ========================================================================= + # Lifecycle Commands + # ========================================================================= start) + show_banner + load_env log_info "Starting $SERVICE_NAME..." - cd "$SERVICES_DIR" - docker compose up -d "$SERVICE_NAME" + cd "$SCRIPT_DIR" + docker compose up -d log_success "$SERVICE_NAME started" + log_info "Waiting for service to be healthy..." + sleep 5 + $0 health ;; stop) + show_banner log_info "Stopping $SERVICE_NAME..." - docker stop "$CONTAINER_NAME" 2>/dev/null || true - docker rm "$CONTAINER_NAME" 2>/dev/null || true + cd "$SCRIPT_DIR" + docker compose down log_success "$SERVICE_NAME stopped" ;; restart) + show_banner $0 stop $0 start ;; + up) + show_banner + load_env + log_info "Starting all services (foreground)..." + cd "$SCRIPT_DIR" + docker compose up + ;; + + down) + show_banner + log_info "Stopping and removing all containers..." + cd "$SCRIPT_DIR" + docker compose down -v + log_success "All containers and volumes removed" + ;; + + # ========================================================================= + # Monitoring Commands + # ========================================================================= logs) docker logs -f "$CONTAINER_NAME" ;; @@ -71,55 +126,230 @@ case "$1" in docker logs --tail 100 "$CONTAINER_NAME" ;; + logs-all) + cd "$SCRIPT_DIR" + docker compose logs -f + ;; + status) + show_banner + log_info "Checking $SERVICE_NAME status..." + echo "" if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then log_success "$SERVICE_NAME is running" - docker ps --filter "name=$CONTAINER_NAME" --format "table {{.Status}}\t{{.Ports}}" + echo "" + docker ps --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" else log_warn "$SERVICE_NAME is not running" fi + echo "" + log_info "All related containers:" + docker ps --filter "name=rwa-admin" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" ;; - shell) - log_info "Entering $SERVICE_NAME container shell..." - docker exec -it "$CONTAINER_NAME" sh + health) + log_info "Checking health endpoint..." + if curl -sf "$HEALTH_ENDPOINT" > /dev/null 2>&1; then + log_success "Health check passed" + curl -s "$HEALTH_ENDPOINT" | jq . 2>/dev/null || curl -s "$HEALTH_ENDPOINT" + else + log_error "Health check failed" + exit 1 + fi ;; + # ========================================================================= + # Database Commands + # ========================================================================= migrate) - log_info "Running database migrations for $SERVICE_NAME..." + show_banner + log_info "Running database migrations (production)..." docker exec "$CONTAINER_NAME" npx prisma migrate deploy log_success "Migrations completed" ;; migrate-dev) - log_info "Running dev migrations for $SERVICE_NAME..." + show_banner + log_info "Running database migrations (development)..." docker exec -it "$CONTAINER_NAME" npx prisma migrate dev log_success "Dev migrations completed" ;; + migrate-status) + log_info "Checking migration status..." + docker exec "$CONTAINER_NAME" npx prisma migrate status + ;; + + prisma-studio) + log_info "Starting Prisma Studio..." + log_warn "Make sure DATABASE_URL is set in your environment" + cd "$SCRIPT_DIR" + npx prisma studio + ;; + + db-push) + log_info "Pushing schema to database (development only)..." + docker exec "$CONTAINER_NAME" npx prisma db push + log_success "Schema pushed to database" + ;; + + db-seed) + log_info "Seeding database..." + docker exec "$CONTAINER_NAME" npx prisma db seed + log_success "Database seeded" + ;; + + # ========================================================================= + # Development Commands + # ========================================================================= + shell) + log_info "Entering $SERVICE_NAME container shell..." + docker exec -it "$CONTAINER_NAME" sh + ;; + + dev) + show_banner + log_info "Starting development mode..." + cd "$SCRIPT_DIR" + npm run start:dev + ;; + + test) + show_banner + log_info "Running tests..." + cd "$SCRIPT_DIR" + npm test + ;; + + test-unit) + log_info "Running unit tests..." + cd "$SCRIPT_DIR" + npm run test:unit + ;; + + test-integration) + log_info "Running integration tests..." + cd "$SCRIPT_DIR" + npm run test:integration + ;; + + test-e2e) + log_info "Running E2E tests..." + cd "$SCRIPT_DIR" + npm run test:e2e + ;; + + lint) + log_info "Running linter..." + cd "$SCRIPT_DIR" + npm run lint + ;; + + format) + log_info "Formatting code..." + cd "$SCRIPT_DIR" + npm run format + ;; + + # ========================================================================= + # Cleanup Commands + # ========================================================================= clean) - log_warn "Cleaning $SERVICE_NAME (removing container and volumes)..." + show_banner + log_warn "Cleaning $SERVICE_NAME (removing containers)..." $0 stop - docker volume rm "${SERVICE_NAME}_node_modules" 2>/dev/null || true log_success "$SERVICE_NAME cleaned" ;; - *) - echo "Usage: $0 {build|build-no-cache|start|stop|restart|logs|logs-tail|status|shell|migrate|migrate-dev|clean}" + clean-all) + show_banner + log_warn "Cleaning $SERVICE_NAME (removing containers, volumes, and images)..." + cd "$SCRIPT_DIR" + docker compose down -v --rmi local + log_success "$SERVICE_NAME fully cleaned" + ;; + + prune) + show_banner + log_warn "Pruning unused Docker resources..." + docker system prune -f + log_success "Docker resources pruned" + ;; + + # ========================================================================= + # Info Commands + # ========================================================================= + info) + show_banner + echo -e "${CYAN}Service Information:${NC}" + echo " Name: $SERVICE_NAME" + echo " Container: $CONTAINER_NAME" + echo " Image: $IMAGE_NAME" + echo " Port: $PORT" + echo " Health: $HEALTH_ENDPOINT" echo "" - echo "Commands:" - echo " build - Build Docker image" - echo " build-no-cache - Build Docker image without cache" - echo " start - Start service" - echo " stop - Stop service" - echo " restart - Restart service" - echo " logs - Follow logs" - echo " logs-tail - Show last 100 lines of logs" - echo " status - Check service status" - echo " shell - Enter container shell" - echo " migrate - Run database migrations (production)" - echo " migrate-dev - Run database migrations (development)" - echo " clean - Remove container and volumes" + echo -e "${CYAN}API Endpoints:${NC}" + echo " Health: GET /api/v1/health" + echo " Check Update: GET /api/v1/versions/check-update" + echo " Create: POST /api/v1/versions" + echo "" + echo -e "${CYAN}Environment Files:${NC}" + echo " .env.example - Template" + echo " .env.development - Local development" + echo " .env.production - Production (uses variable references)" + echo " .env.test - Testing" + ;; + + # ========================================================================= + # Help + # ========================================================================= + *) + show_banner + echo "Usage: $0 " + echo "" + echo -e "${CYAN}Build Commands:${NC}" + echo " build Build Docker image" + echo " build-no-cache Build Docker image without cache" + echo "" + echo -e "${CYAN}Lifecycle Commands:${NC}" + echo " start Start all services (detached)" + echo " stop Stop all services" + echo " restart Restart all services" + echo " up Start all services (foreground)" + echo " down Stop and remove all containers and volumes" + echo "" + echo -e "${CYAN}Monitoring Commands:${NC}" + echo " logs Follow service logs" + echo " logs-tail Show last 100 lines of logs" + echo " logs-all Follow all container logs" + echo " status Check service status" + echo " health Check health endpoint" + echo "" + echo -e "${CYAN}Database Commands:${NC}" + echo " migrate Run migrations (production)" + echo " migrate-dev Run migrations (development)" + echo " migrate-status Check migration status" + echo " prisma-studio Open Prisma Studio" + echo " db-push Push schema to database" + echo " db-seed Seed database" + echo "" + echo -e "${CYAN}Development Commands:${NC}" + echo " shell Enter container shell" + echo " dev Start in development mode" + echo " test Run all tests" + echo " test-unit Run unit tests" + echo " test-integration Run integration tests" + echo " test-e2e Run E2E tests" + echo " lint Run linter" + echo " format Format code" + echo "" + echo -e "${CYAN}Cleanup Commands:${NC}" + echo " clean Remove containers" + echo " clean-all Remove containers, volumes, and images" + echo " prune Prune unused Docker resources" + echo "" + echo -e "${CYAN}Info Commands:${NC}" + echo " info Show service information" exit 1 ;; esac diff --git a/backend/services/admin-service/docker-compose.yml b/backend/services/admin-service/docker-compose.yml new file mode 100644 index 00000000..300fedda --- /dev/null +++ b/backend/services/admin-service/docker-compose.yml @@ -0,0 +1,89 @@ +# ============================================================================= +# Admin Service - Docker Compose Configuration +# ============================================================================= +# 用途: 本地开发和独立部署 admin-service +# 启动: docker compose up -d +# ============================================================================= + +services: + admin-service: + build: . + container_name: rwa-admin-service + ports: + - "3010:3010" + environment: + # Application + - NODE_ENV=production + - APP_PORT=3010 + - API_PREFIX=api/v1 + # Database + - DATABASE_URL=postgresql://postgres:password@postgres:5432/rwa_admin?schema=public + # JWT + - JWT_SECRET=your-admin-jwt-secret-change-in-production + - JWT_EXPIRES_IN=7d + # Redis (可选) + - REDIS_HOST=redis + - REDIS_PORT=6379 + - REDIS_PASSWORD= + - REDIS_DB=9 + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3010/api/v1/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + restart: unless-stopped + networks: + - admin-network + + postgres: + image: postgres:16-alpine + container_name: rwa-admin-postgres + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=password + - POSTGRES_DB=rwa_admin + ports: + - "5433:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d rwa_admin"] + interval: 5s + timeout: 5s + retries: 10 + restart: unless-stopped + networks: + - admin-network + + # Redis (可选,用于缓存) + redis: + image: redis:7-alpine + container_name: rwa-admin-redis + ports: + - "6380:6379" + volumes: + - redis_data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 10 + restart: unless-stopped + networks: + - admin-network + +volumes: + postgres_data: + name: admin-service-postgres-data + redis_data: + name: admin-service-redis-data + +networks: + admin-network: + name: admin-service-network + driver: bridge diff --git a/backend/services/admin-service/docs/DEPLOYMENT.md b/backend/services/admin-service/docs/DEPLOYMENT.md index f72ff624..0442721e 100644 --- a/backend/services/admin-service/docs/DEPLOYMENT.md +++ b/backend/services/admin-service/docs/DEPLOYMENT.md @@ -4,11 +4,12 @@ - [1. 部署概述](#1-部署概述) - [2. 环境准备](#2-环境准备) -- [3. 本地部署](#3-本地部署) -- [4. Docker 部署](#4-docker-部署) -- [5. 生产环境部署](#5-生产环境部署) -- [6. 监控和维护](#6-监控和维护) -- [7. 故障排查](#7-故障排查) +- [3. 快速开始](#3-快速开始) +- [4. 本地部署](#4-本地部署) +- [5. Docker 部署](#5-docker-部署) +- [6. 生产环境部署](#6-生产环境部署) +- [7. 监控和维护](#7-监控和维护) +- [8. 故障排查](#8-故障排查) --- @@ -148,9 +149,96 @@ sudo ufw status --- -## 3. 本地部署 +## 3. 快速开始 -### 3.1 克隆代码 +### 3.1 一键启动 (推荐) + +使用 `deploy.sh` 脚本快速启动所有服务: + +```bash +# 进入项目目录 +cd backend/services/admin-service + +# 启动所有服务 (包含 PostgreSQL, Redis) +./deploy.sh start + +# 检查服务状态 +./deploy.sh status + +# 查看日志 +./deploy.sh logs + +# 健康检查 +./deploy.sh health +``` + +### 3.2 验证部署 + +```bash +# 健康检查 +curl http://localhost:3010/api/v1/health + +# 预期响应 +{ + "status": "ok", + "service": "admin-service", + "timestamp": "2025-12-02T12:00:00.000Z" +} +``` + +### 3.3 环境文件说明 + +| 文件 | 用途 | 说明 | +|------|------|------| +| `.env.example` | 配置模板 | 所有配置项的参考 | +| `.env.development` | 本地开发 | 使用本地数据库连接 | +| `.env.production` | 生产环境 | 使用变量引用,部署时注入 | +| `.env.test` | 测试环境 | 独立的测试数据库 | +| `.env` | 实际使用 | 复制自上述文件,不提交到 Git | + +### 3.4 deploy.sh 命令速查 + +```bash +# 构建 +./deploy.sh build # 构建 Docker 镜像 +./deploy.sh build-no-cache # 无缓存构建 + +# 生命周期 +./deploy.sh start # 启动所有服务 +./deploy.sh stop # 停止所有服务 +./deploy.sh restart # 重启服务 +./deploy.sh up # 前台启动 (查看日志) +./deploy.sh down # 停止并删除容器和卷 + +# 监控 +./deploy.sh logs # 实时日志 +./deploy.sh logs-tail # 最近 100 行日志 +./deploy.sh status # 服务状态 +./deploy.sh health # 健康检查 + +# 数据库 +./deploy.sh migrate # 生产迁移 +./deploy.sh migrate-dev # 开发迁移 +./deploy.sh prisma-studio # Prisma GUI + +# 开发 +./deploy.sh dev # 开发模式 +./deploy.sh test # 运行测试 +./deploy.sh shell # 进入容器 + +# 清理 +./deploy.sh clean # 清理容器 +./deploy.sh clean-all # 清理容器、卷和镜像 + +# 信息 +./deploy.sh info # 显示服务信息 +``` + +--- + +## 4. 本地部署 + +### 4.1 克隆代码 ```bash cd /opt @@ -161,24 +249,24 @@ cd rwa-durian/backend/services/admin-service sudo chown -R $USER:$USER /opt/rwa-durian ``` -### 3.2 安装依赖 +### 4.2 安装依赖 ```bash npm ci --omit=dev ``` -### 3.3 环境配置 +### 4.3 环境配置 创建 `.env.production`: ```env # 应用配置 NODE_ENV=production -APP_PORT=3005 +APP_PORT=3010 API_PREFIX=api/v1 # 数据库配置 -DATABASE_URL=postgresql://admin_service:your_secure_password@localhost:5432/admin_service_prod?schema=public +DATABASE_URL=postgresql://admin_service:your_secure_password@localhost:5432/rwa_admin?schema=public # 日志配置 LOG_LEVEL=info @@ -190,7 +278,7 @@ CORS_ORIGIN=https://admin.rwadurian.com,https://app.rwadurian.com JWT_SECRET=your_super_secret_jwt_key_change_in_production ``` -### 3.4 数据库迁移 +### 4.4 数据库迁移 ```bash # 生成 Prisma Client @@ -203,13 +291,13 @@ npm run prisma:migrate:deploy psql -U admin_service -d admin_service_prod -f database/init.sql ``` -### 3.5 构建应用 +### 4.5 构建应用 ```bash npm run build ``` -### 3.6 使用 PM2 启动 +### 4.6 使用 PM2 启动 创建 `ecosystem.config.js`: @@ -223,7 +311,7 @@ module.exports = { exec_mode: 'cluster', env: { NODE_ENV: 'production', - APP_PORT: 3005, + APP_PORT: 3010, }, env_file: '.env.production', error_file: 'logs/error.log', @@ -260,7 +348,7 @@ pm2 stop admin-service pm2 delete admin-service ``` -### 3.7 设置开机自启动 +### 4.7 设置开机自启动 ```bash # 保存 PM2 进程列表 @@ -273,17 +361,17 @@ pm2 startup systemd # sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u your_user --hp /home/your_user ``` -### 3.8 验证部署 +### 4.8 验证部署 ```bash # 检查服务状态 -curl http://localhost:3005/api/v1/health +curl http://localhost:3010/api/v1/health # 预期响应 -{"status": "ok"} +{"status": "ok", "service": "admin-service", "timestamp": "..."} # 检查版本查询 -curl http://localhost:3005/api/v1/version/check?platform=android&versionCode=1 +curl "http://localhost:3010/api/v1/versions/check-update?platform=android¤tVersionCode=1" # PM2 状态 pm2 status @@ -291,11 +379,27 @@ pm2 status --- -## 4. Docker 部署 +## 5. Docker 部署 -### 4.1 Dockerfile +### 5.1 使用 deploy.sh (推荐) -**Dockerfile**: +```bash +# 构建镜像 +./deploy.sh build + +# 启动所有服务 +./deploy.sh start + +# 查看状态 +./deploy.sh status + +# 运行数据库迁移 +./deploy.sh migrate +``` + +### 5.2 Dockerfile + +**已配置的 Dockerfile** 特性: ```dockerfile # 构建阶段 FROM node:20-alpine AS builder @@ -335,200 +439,198 @@ COPY --from=builder /app/dist ./dist COPY --from=builder /app/prisma ./prisma # 暴露端口 -EXPOSE 3005 +EXPOSE 3010 # 健康检查 HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=40s \ - CMD wget -q --spider http://localhost:3005/api/v1/health || exit 1 + CMD curl -f http://localhost:3010/api/v1/health || exit 1 # 启动命令 CMD ["node", "dist/main.js"] ``` -### 4.2 Docker Compose +### 5.3 Docker Compose + +**docker-compose.yml** 服务架构: + +``` +┌─────────────────────────────────────┐ +│ admin-service (3010) │ +│ NestJS Application │ +└──────────────┬──────────────────────┘ + │ + ┌───────┴───────┐ + │ │ + ▼ ▼ +┌──────────────┐ ┌──────────────┐ +│ PostgreSQL │ │ Redis │ +│ (5433) │ │ (6380) │ +└──────────────┘ └──────────────┘ +``` + +**端口映射** (避免与其他服务冲突): +- admin-service: 3010 +- PostgreSQL: 5433 (外部) → 5432 (内部) +- Redis: 6380 (外部) → 6379 (内部) -**docker-compose.yml**: ```yaml -version: '3.8' - services: admin-service: - build: - context: . - dockerfile: Dockerfile - container_name: admin-service - restart: unless-stopped + build: . + container_name: rwa-admin-service ports: - - "3005:3005" + - "3010:3010" environment: - NODE_ENV=production - - APP_PORT=3005 + - APP_PORT=3010 - API_PREFIX=api/v1 - - DATABASE_URL=postgresql://postgres:password@postgres:5432/admin_service_prod + - DATABASE_URL=postgresql://postgres:password@postgres:5432/rwa_admin?schema=public + - JWT_SECRET=your-admin-jwt-secret-change-in-production + - REDIS_HOST=redis + - REDIS_PORT=6379 depends_on: postgres: condition: service_healthy healthcheck: - test: ["CMD", "wget", "-q", "--spider", "http://localhost:3005/api/v1/health"] + test: ["CMD", "curl", "-f", "http://localhost:3010/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s - networks: - - admin-network + restart: unless-stopped postgres: image: postgres:16-alpine - container_name: admin-postgres - restart: unless-stopped + container_name: rwa-admin-postgres environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=password - - POSTGRES_DB=admin_service_prod + - POSTGRES_DB=rwa_admin ports: - - "5432:5432" + - "5433:5432" volumes: - postgres_data:/var/lib/postgresql/data - - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql + - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql:ro healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres"] + test: ["CMD-SHELL", "pg_isready -U postgres -d rwa_admin"] interval: 5s timeout: 5s retries: 10 - networks: - - admin-network + restart: unless-stopped + + redis: + image: redis:7-alpine + container_name: rwa-admin-redis + ports: + - "6380:6379" + volumes: + - redis_data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 10 + restart: unless-stopped volumes: postgres_data: - -networks: - admin-network: - driver: bridge + name: admin-service-postgres-data + redis_data: + name: admin-service-redis-data ``` -### 4.3 Docker 部署步骤 +### 5.4 Docker 部署步骤 ```bash -# 1. 构建镜像 -docker-compose build +# 使用 deploy.sh (推荐) +./deploy.sh build # 构建镜像 +./deploy.sh start # 启动服务 +./deploy.sh migrate # 运行迁移 +./deploy.sh logs # 查看日志 +./deploy.sh status # 查看状态 +./deploy.sh stop # 停止服务 +./deploy.sh down # 清理 (包括数据) -# 2. 启动服务 -docker-compose up -d - -# 3. 运行数据库迁移 -docker-compose exec admin-service npx prisma migrate deploy - -# 4. 查看日志 -docker-compose logs -f admin-service - -# 5. 查看状态 -docker-compose ps - -# 6. 停止服务 -docker-compose down - -# 7. 清理 (包括数据) -docker-compose down -v +# 或使用原生 docker compose +docker compose build +docker compose up -d +docker compose exec admin-service npx prisma migrate deploy +docker compose logs -f admin-service +docker compose ps +docker compose down +docker compose down -v ``` -### 4.4 Docker 健康检查 +### 5.5 Docker 健康检查 ```bash # 检查容器健康状态 docker ps # 查看健康检查日志 -docker inspect admin-service | jq '.[0].State.Health' +docker inspect rwa-admin-service | jq '.[0].State.Health' # 手动健康检查 -docker exec admin-service wget -q -O - http://localhost:3005/api/v1/health +docker exec rwa-admin-service curl -f http://localhost:3010/api/v1/health ``` --- -## 5. 生产环境部署 +## 6. 生产环境部署 -### 5.1 Nginx 反向代理 +### 6.1 Nginx 反向代理 **安装 Nginx**: ```bash sudo apt install -y nginx ``` -**配置文件** (`/etc/nginx/sites-available/admin-service`): +**集成到 RWA API 网关** (`/etc/nginx/sites-available/rwaapi.szaiai.com.conf`): ```nginx upstream admin_service { least_conn; - server 127.0.0.1:3005; - # server 127.0.0.1:3006; # 多实例负载均衡 - # server 127.0.0.1:3007; -} - -server { - listen 80; - listen [::]:80; - server_name admin-api.rwadurian.com; - - # 重定向到 HTTPS - return 301 https://$server_name$request_uri; + server 192.168.1.111:3010; + # server 192.168.1.112:3010; # 多实例负载均衡 } +# 在主 server 块中添加 admin-service 路由 server { listen 443 ssl http2; - listen [::]:443 ssl http2; - server_name admin-api.rwadurian.com; + server_name rwaapi.szaiai.com; - # SSL 证书 - ssl_certificate /etc/letsencrypt/live/admin-api.rwadurian.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/admin-api.rwadurian.com/privkey.pem; + # SSL 配置 (已在主配置中设置) + ssl_certificate /etc/letsencrypt/live/rwaapi.szaiai.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/rwaapi.szaiai.com/privkey.pem; + include /etc/nginx/snippets/ssl-params.conf; - # SSL 配置 - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; - ssl_prefer_server_ciphers on; - - # 日志 - access_log /var/log/nginx/admin-service-access.log; - error_log /var/log/nginx/admin-service-error.log; - - # 代理配置 - location /api/v1/ { + # Admin Service 路由 - 版本管理 + location /api/v1/versions { + include /etc/nginx/snippets/proxy-params.conf; + include /etc/nginx/snippets/cors-params.conf; proxy_pass http://admin_service; - proxy_http_version 1.1; - - # 请求头 - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - # 超时配置 - proxy_connect_timeout 60s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - - # 缓存禁用 (API 不需要) - proxy_cache_bypass $http_upgrade; } - # 健康检查端点 - location /health { - proxy_pass http://admin_service/api/v1/health; - access_log off; + # Admin Service 路由 - 管理接口 (预留) + location /api/v1/admin { + include /etc/nginx/snippets/proxy-params.conf; + include /etc/nginx/snippets/cors-params.conf; + proxy_pass http://admin_service; } + + # ... 其他服务路由 (identity, wallet, etc.) } ``` **启用配置**: ```bash -sudo ln -s /etc/nginx/sites-available/admin-service /etc/nginx/sites-enabled/ +# 测试配置 sudo nginx -t + +# 重载配置 sudo systemctl reload nginx ``` -### 5.2 SSL 证书 (Let's Encrypt) +### 6.2 SSL 证书 (Let's Encrypt) ```bash # 安装 Certbot @@ -545,7 +647,7 @@ sudo crontab -e # 添加: 0 3 * * * certbot renew --quiet ``` -### 5.3 日志管理 +### 6.3 日志管理 #### 日志轮转 @@ -583,7 +685,7 @@ sudo tail -f /var/log/nginx/admin-service-access.log sudo tail -f /var/log/nginx/admin-service-error.log ``` -### 5.4 数据库备份 +### 6.4 数据库备份 #### 自动备份脚本 @@ -635,7 +737,7 @@ gunzip admin_service_20250103_020000.backup.gz pg_restore -U admin_service -d admin_service_prod -v admin_service_20250103_020000.backup ``` -### 5.5 监控告警 +### 6.5 监控告警 #### PM2 监控 @@ -655,7 +757,7 @@ pm2 monit ```bash #!/bin/bash -HEALTH_URL="http://localhost:3005/api/v1/health" +HEALTH_URL="http://localhost:3010/api/v1/health" ALERT_EMAIL="admin@rwadurian.com" response=$(curl -s -o /dev/null -w "%{http_code}" $HEALTH_URL) @@ -679,9 +781,9 @@ crontab -e --- -## 6. 监控和维护 +## 7. 监控和维护 -### 6.1 性能监控 +### 7.1 性能监控 #### 应用指标 @@ -709,7 +811,7 @@ sudo -u postgres psql -d admin_service_prod -c "SELECT query, calls, total_time, sudo -u postgres psql -c "SELECT pg_size_pretty(pg_database_size('admin_service_prod'));" ``` -### 6.2 日常维护 +### 7.2 日常维护 #### 更新应用 @@ -735,7 +837,7 @@ npm run build pm2 restart admin-service # 7. 验证 -curl http://localhost:3005/api/v1/health +curl http://localhost:3010/api/v1/health # 8. 查看日志 pm2 logs admin-service --lines 50 @@ -754,7 +856,7 @@ sudo -u postgres psql -d admin_service_prod -c "VACUUM ANALYZE;" sudo -u postgres psql -d admin_service_prod -c "REINDEX DATABASE admin_service_prod;" ``` -### 6.3 扩容方案 +### 7.3 扩容方案 #### 垂直扩容 (增加资源) @@ -777,9 +879,9 @@ pm2 restart admin-service ```nginx upstream admin_service { least_conn; - server 192.168.1.10:3005 weight=1; - server 192.168.1.11:3005 weight=1; - server 192.168.1.12:3005 weight=1; + server 192.168.1.111:3010 weight=1; + server 192.168.1.112:3010 weight=1; + server 192.168.1.113:3010 weight=1; } ``` @@ -791,9 +893,9 @@ sudo systemctl reload nginx --- -## 7. 故障排查 +## 8. 故障排查 -### 7.1 常见问题 +### 8.1 常见问题 #### 问题 1: 服务无法启动 @@ -905,7 +1007,7 @@ sudo apt install -y redis-server npm install @nestjs/cache-manager cache-manager cache-manager-redis-store ``` -### 7.2 日志分析 +### 8.2 日志分析 #### 错误日志 @@ -934,7 +1036,7 @@ node --prof dist/main.js node --prof-process isolate-*.log > profile.txt ``` -### 7.3 回滚策略 +### 8.3 回滚策略 #### 应用回滚 @@ -953,7 +1055,7 @@ DATABASE_URL="..." npx prisma migrate resolve --rolled-back 20250103100000_add_n pm2 start admin-service # 5. 验证 -curl http://localhost:3005/api/v1/health +curl http://localhost:3010/api/v1/health ``` #### 数据库回滚 @@ -965,9 +1067,9 @@ pg_restore -U admin_service -d admin_service_prod -c admin_service_20250103_0200 --- -## 8. 安全加固 +## 9. 安全加固 -### 8.1 应用安全 +### 9.1 应用安全 ```bash # 1. 限制 Node.js 进程权限 @@ -983,7 +1085,7 @@ sudo chmod -R 750 /opt/rwa-durian/backend/services/admin-service chmod 600 .env.production ``` -### 8.2 数据库安全 +### 9.2 数据库安全 ```bash # 1. 修改默认密码 @@ -999,7 +1101,7 @@ host admin_service_prod admin_service 127.0.0.1/32 md5 ssl = on ``` -### 8.3 Nginx 安全 +### 9.3 Nginx 安全 ```nginx # 隐藏版本号 @@ -1019,9 +1121,9 @@ server { --- -## 9. 快速参考 +## 10. 快速参考 -### 9.1 常用命令 +### 10.1 常用命令 ```bash # PM2 管理 @@ -1043,7 +1145,7 @@ npm run build npm run start:prod # 健康检查 -curl http://localhost:3005/api/v1/health +curl http://localhost:3010/api/v1/health # Nginx sudo systemctl status nginx @@ -1051,7 +1153,45 @@ sudo systemctl reload nginx sudo nginx -t ``` -### 9.2 检查清单 +### 10.2 deploy.sh 命令速查 + +```bash +# 构建 +./deploy.sh build # 构建镜像 +./deploy.sh build-no-cache # 无缓存构建 + +# 生命周期 +./deploy.sh start # 启动服务 +./deploy.sh stop # 停止服务 +./deploy.sh restart # 重启服务 +./deploy.sh up # 前台启动 +./deploy.sh down # 停止并清理 + +# 监控 +./deploy.sh logs # 实时日志 +./deploy.sh logs-tail # 最近日志 +./deploy.sh status # 服务状态 +./deploy.sh health # 健康检查 + +# 数据库 +./deploy.sh migrate # 生产迁移 +./deploy.sh migrate-dev # 开发迁移 +./deploy.sh prisma-studio # Prisma GUI + +# 开发 +./deploy.sh dev # 开发模式 +./deploy.sh test # 运行测试 +./deploy.sh shell # 进入容器 + +# 清理 +./deploy.sh clean # 清理容器 +./deploy.sh clean-all # 完全清理 + +# 信息 +./deploy.sh info # 服务信息 +``` + +### 10.3 检查清单 #### 部署前