feat(admin-service): 添加完整的量产部署设施

参考 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 <noreply@anthropic.com>
This commit is contained in:
Developer 2025-12-02 19:34:31 -08:00
parent 79e2b9bfdd
commit eae1350f35
6 changed files with 752 additions and 187 deletions

View File

@ -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/

View File

@ -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

View File

@ -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

View File

@ -1,6 +1,8 @@
#!/bin/bash
# =============================================================================
# Admin Service - Individual Deployment Script
# Admin Service - Deployment Script
# =============================================================================
# 用法: ./deploy.sh <command>
# =============================================================================
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 <command>"
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

View File

@ -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

View File

@ -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&currentVersionCode=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 检查清单
#### 部署前