rwadurian/frontend/mobile-upgrade/docs/DEPLOYMENT.md

570 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Mobile Upgrade Admin - 部署指南
## 部署概述
本文档描述 Mobile Upgrade Admin 前端应用的部署方案包括本地构建、Docker 容器化和生产环境部署。
## 部署架构
```
┌─────────────────────────────────────────────────────────────┐
│ Nginx / Caddy │
│ (Reverse Proxy) │
└─────────────────┬───────────────────────┬───────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Mobile Upgrade │ │ Admin Service │
│ Frontend (3001)│ │ Backend (3000) │
└─────────────────┘ └─────────────────┘
```
## 环境要求
| 环境 | 要求 |
|------|------|
| Node.js | >= 18.x |
| npm | >= 9.x |
| Docker | >= 20.x (可选) |
| 内存 | >= 512MB |
| 磁盘 | >= 500MB |
## 环境变量配置
### 开发环境
```bash
# .env.local
NEXT_PUBLIC_API_URL=http://localhost:3000
```
### 生产环境
```bash
# .env.production
NEXT_PUBLIC_API_URL=https://api.example.com
```
| 变量 | 说明 | 默认值 |
|------|------|--------|
| NEXT_PUBLIC_API_URL | Admin Service API 地址 | http://localhost:3000 |
| PORT | 应用监听端口 | 3000 |
## 部署方式
### 方式一:本地构建部署
#### 1. 构建生产版本
```bash
cd frontend/mobile-upgrade
# 安装依赖
npm ci
# 构建
npm run build
```
构建产物在 `.next/` 目录。
#### 2. 启动生产服务
```bash
# 使用 Node.js 直接运行
npm run start
# 或指定端口
PORT=3001 npm run start
```
#### 3. 使用 PM2 管理
```bash
# 安装 PM2
npm install -g pm2
# 启动应用
pm2 start npm --name "mobile-upgrade" -- start
# 查看状态
pm2 status
# 查看日志
pm2 logs mobile-upgrade
# 重启
pm2 restart mobile-upgrade
# 停止
pm2 stop mobile-upgrade
```
PM2 配置文件:
```javascript
// ecosystem.config.js
module.exports = {
apps: [{
name: 'mobile-upgrade',
script: 'npm',
args: 'start',
cwd: '/path/to/mobile-upgrade',
env: {
NODE_ENV: 'production',
PORT: 3001,
},
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '500M',
}],
}
```
### 方式二Docker 容器部署
#### 1. Dockerfile
```dockerfile
# Dockerfile
FROM node:18-alpine AS base
# 安装依赖阶段
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# 构建阶段
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 设置环境变量
ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
RUN npm run build
# 运行阶段
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# 复制构建产物
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
ENV HOSTNAME "0.0.0.0"
CMD ["node", "server.js"]
```
#### 2. 更新 next.config.js
```javascript
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone', // 启用独立输出模式
// ... 其他配置
}
module.exports = nextConfig
```
#### 3. 构建 Docker 镜像
```bash
# 构建镜像
docker build \
--build-arg NEXT_PUBLIC_API_URL=https://api.example.com \
-t mobile-upgrade:latest \
.
# 运行容器
docker run -d \
--name mobile-upgrade \
-p 3001:3000 \
mobile-upgrade:latest
```
#### 4. Docker Compose
```yaml
# docker-compose.yml
version: '3.8'
services:
mobile-upgrade:
build:
context: .
args:
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://admin-service:3000}
image: mobile-upgrade:latest
container_name: mobile-upgrade
ports:
- "3001:3000"
environment:
- NODE_ENV=production
restart: unless-stopped
networks:
- rwa-network
depends_on:
- admin-service
networks:
rwa-network:
external: true
```
启动命令:
```bash
# 启动
docker-compose up -d
# 查看日志
docker-compose logs -f mobile-upgrade
# 停止
docker-compose down
```
### 方式三:静态导出部署
适用于不需要 SSR 的场景。
#### 1. 配置静态导出
```javascript
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
trailingSlash: true,
images: {
unoptimized: true,
},
}
module.exports = nextConfig
```
#### 2. 构建静态文件
```bash
npm run build
```
静态文件输出到 `out/` 目录。
#### 3. 使用 Nginx 部署
```nginx
# nginx.conf
server {
listen 80;
server_name upgrade.example.com;
root /var/www/mobile-upgrade;
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://admin-service:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
```
## 反向代理配置
### Nginx 配置
```nginx
# /etc/nginx/sites-available/mobile-upgrade
upstream mobile_upgrade {
server 127.0.0.1:3001;
}
upstream admin_service {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name upgrade.example.com;
# 前端应用
location / {
proxy_pass http://mobile_upgrade;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
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;
}
# API 代理
location /api {
proxy_pass http://admin_service;
proxy_http_version 1.1;
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;
# 大文件上传支持
client_max_body_size 200M;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
}
}
```
### Caddy 配置
```caddyfile
# Caddyfile
upgrade.example.com {
reverse_proxy /api/* admin-service:3000
reverse_proxy /* mobile-upgrade:3001
}
```
## 健康检查
### 应用健康检查
```typescript
// src/app/api/health/route.ts
export async function GET() {
return Response.json({
status: 'healthy',
timestamp: new Date().toISOString(),
})
}
```
### Docker 健康检查
```dockerfile
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
```
### Kubernetes 探针
```yaml
livenessProbe:
httpGet:
path: /api/health
port: 3000
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /api/health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
```
## CI/CD 集成
### GitHub Actions
```yaml
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
paths:
- 'frontend/mobile-upgrade/**'
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'npm'
cache-dependency-path: frontend/mobile-upgrade/package-lock.json
- name: Install dependencies
working-directory: frontend/mobile-upgrade
run: npm ci
- name: Build
working-directory: frontend/mobile-upgrade
run: npm run build
env:
NEXT_PUBLIC_API_URL: ${{ secrets.API_URL }}
- name: Build Docker image
working-directory: frontend/mobile-upgrade
run: |
docker build \
--build-arg NEXT_PUBLIC_API_URL=${{ secrets.API_URL }} \
-t mobile-upgrade:${{ github.sha }} \
.
- name: Push to registry
run: |
docker tag mobile-upgrade:${{ github.sha }} registry.example.com/mobile-upgrade:${{ github.sha }}
docker push registry.example.com/mobile-upgrade:${{ github.sha }}
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
docker pull registry.example.com/mobile-upgrade:${{ github.sha }}
docker stop mobile-upgrade || true
docker rm mobile-upgrade || true
docker run -d \
--name mobile-upgrade \
-p 3001:3000 \
--restart unless-stopped \
registry.example.com/mobile-upgrade:${{ github.sha }}
```
## 监控和日志
### 日志收集
```bash
# Docker 日志
docker logs -f mobile-upgrade
# PM2 日志
pm2 logs mobile-upgrade
# 日志文件位置
/var/log/mobile-upgrade/access.log
/var/log/mobile-upgrade/error.log
```
### 性能监控
建议集成:
- **Prometheus + Grafana**: 指标监控
- **Sentry**: 错误追踪
- **Datadog / New Relic**: APM
### 集成 Sentry
```bash
npm install @sentry/nextjs
```
```typescript
// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs'
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tracesSampleRate: 0.1,
})
```
## 故障排查
### 常见问题
| 问题 | 可能原因 | 解决方案 |
|------|----------|----------|
| 页面空白 | 构建失败 | 检查构建日志 |
| API 请求失败 | CORS / 网络 | 检查代理配置 |
| 静态资源 404 | 路径配置 | 检查 basePath 配置 |
| 内存不足 | 并发过高 | 增加实例或内存 |
### 调试命令
```bash
# 检查进程
ps aux | grep node
# 检查端口
netstat -tlnp | grep 3001
# 检查容器
docker ps -a
docker inspect mobile-upgrade
# 检查日志
docker logs --tail 100 mobile-upgrade
```
## 回滚策略
### Docker 回滚
```bash
# 查看历史版本
docker images mobile-upgrade
# 回滚到指定版本
docker stop mobile-upgrade
docker rm mobile-upgrade
docker run -d \
--name mobile-upgrade \
-p 3001:3000 \
mobile-upgrade:previous-tag
```
### PM2 回滚
```bash
# 保存当前配置
pm2 save
# 回滚
pm2 reload ecosystem.config.js --update-env
```
## 安全建议
1. **环境变量**:不要在代码中硬编码敏感信息
2. **HTTPS**:生产环境强制使用 HTTPS
3. **CSP**:配置内容安全策略
4. **更新依赖**:定期更新依赖修复安全漏洞
5. **访问控制**:配置合适的访问权限
## 相关文档
- [架构文档](./ARCHITECTURE.md)
- [API 文档](./API.md)
- [开发指南](./DEVELOPMENT.md)
- [测试指南](./TESTING.md)