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

12 KiB
Raw Permalink Blame History

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

环境变量配置

开发环境

# .env.local
NEXT_PUBLIC_API_URL=http://localhost:3000

生产环境

# .env.production
NEXT_PUBLIC_API_URL=https://api.example.com
变量 说明 默认值
NEXT_PUBLIC_API_URL Admin Service API 地址 http://localhost:3000
PORT 应用监听端口 3000

部署方式

方式一:本地构建部署

1. 构建生产版本

cd frontend/mobile-upgrade

# 安装依赖
npm ci

# 构建
npm run build

构建产物在 .next/ 目录。

2. 启动生产服务

# 使用 Node.js 直接运行
npm run start

# 或指定端口
PORT=3001 npm run start

3. 使用 PM2 管理

# 安装 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 配置文件:

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

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',  // 启用独立输出模式
  // ... 其他配置
}

module.exports = nextConfig

3. 构建 Docker 镜像

# 构建镜像
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

# 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

启动命令:

# 启动
docker-compose up -d

# 查看日志
docker-compose logs -f mobile-upgrade

# 停止
docker-compose down

方式三:静态导出部署

适用于不需要 SSR 的场景。

1. 配置静态导出

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',
  trailingSlash: true,
  images: {
    unoptimized: true,
  },
}

module.exports = nextConfig

2. 构建静态文件

npm run build

静态文件输出到 out/ 目录。

3. 使用 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 配置

# /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
upgrade.example.com {
    reverse_proxy /api/* admin-service:3000
    reverse_proxy /* mobile-upgrade:3001
}

健康检查

应用健康检查

// src/app/api/health/route.ts
export async function GET() {
  return Response.json({
    status: 'healthy',
    timestamp: new Date().toISOString(),
  })
}

Docker 健康检查

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 探针

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

# .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 }}            

监控和日志

日志收集

# 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

npm install @sentry/nextjs
// 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 配置
内存不足 并发过高 增加实例或内存

调试命令

# 检查进程
ps aux | grep node

# 检查端口
netstat -tlnp | grep 3001

# 检查容器
docker ps -a
docker inspect mobile-upgrade

# 检查日志
docker logs --tail 100 mobile-upgrade

回滚策略

Docker 回滚

# 查看历史版本
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 回滚

# 保存当前配置
pm2 save

# 回滚
pm2 reload ecosystem.config.js --update-env

安全建议

  1. 环境变量:不要在代码中硬编码敏感信息
  2. HTTPS:生产环境强制使用 HTTPS
  3. CSP:配置内容安全策略
  4. 更新依赖:定期更新依赖修复安全漏洞
  5. 访问控制:配置合适的访问权限

相关文档