Files
admin-vben/docs/部署文档.md

14 KiB
Raw Permalink Blame History

部署文档

部署概述

AIOTAGRO 管理系统支持多种部署方式,包括开发环境部署、测试环境部署和生产环境部署。本文档详细说明各种部署场景的配置和步骤。

环境要求

服务器要求

环境 CPU 内存 磁盘 网络
开发环境 2核 4GB 20GB 10Mbps
测试环境 4核 8GB 50GB 50Mbps
生产环境 8核 16GB 100GB 100Mbps

软件要求

软件 版本 说明
Node.js 18.0.0+ JavaScript 运行时
pnpm 8.0.0+ 包管理器
Nginx 1.20.0+ Web 服务器
Git 2.30.0+ 版本控制

开发环境部署

本地开发环境

1. 环境准备

# 安装 Node.js
# 访问 https://nodejs.org/ 下载安装包

# 安装 pnpm
npm install -g pnpm

# 验证安装
node --version
pnpm --version

2. 项目初始化

# 克隆项目
git clone https://github.com/aiotagro/yudao-ui-admin-vben.git
cd yudao-ui-admin-vben

# 安装依赖
pnpm install

# 启动开发服务器
pnpm dev:antd

3. 访问应用

打开浏览器访问: http://localhost:3000

Docker 开发环境

1. Dockerfile 配置

# Dockerfile.dev
FROM node:18-alpine

WORKDIR /app

# 复制 package.json 和 pnpm-lock.yaml
COPY package.json pnpm-lock.yaml ./

# 安装依赖
RUN npm install -g pnpm && pnpm install

# 复制源代码
COPY . .

# 暴露端口
EXPOSE 3000

# 启动开发服务器
CMD ["pnpm", "dev:antd"]

2. docker-compose 配置

# docker-compose.dev.yml
version: '3.8'
services:
  frontend:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development

3. 启动服务

# 构建并启动服务
docker-compose -f docker-compose.dev.yml up --build

# 后台运行
docker-compose -f docker-compose.dev.yml up -d

测试环境部署

手动部署

1. 服务器准备

# 登录服务器
ssh user@test-server

# 创建项目目录
mkdir -p /opt/aiotagro/frontend
cd /opt/aiotagro/frontend

# 克隆代码
git clone https://github.com/aiotagro/yudao-ui-admin-vben.git .

2. 环境配置

# 安装 Node.js
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs

# 安装 pnpm
npm install -g pnpm

# 安装依赖
pnpm install

3. 构建应用

# 构建生产版本
pnpm build:antd

# 检查构建结果
ls -la dist/

4. 配置 Nginx

# /etc/nginx/sites-available/aiotagro-test
server {
    listen 80;
    server_name test.aiotagro.com;
    
    root /opt/aiotagro/frontend/dist;
    index index.html;
    
    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    
    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # SPA 路由支持
    location / {
        try_files $uri $uri/ /index.html;
    }
    
    # API 代理
    location /api/ {
        proxy_pass http://backend-server:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

5. 启用站点

# 创建符号链接
sudo ln -s /etc/nginx/sites-available/aiotagro-test /etc/nginx/sites-enabled/

# 测试配置
sudo nginx -t

# 重启 Nginx
sudo systemctl restart nginx

自动化部署脚本

#!/bin/bash
# deploy-test.sh

set -e

# 配置变量
PROJECT_DIR="/opt/aiotagro/frontend"
BACKUP_DIR="/opt/aiotagro/backups"
BRANCH="test"

echo "开始部署 AIOTAGRO 测试环境..."

# 备份当前版本
if [ -d "$PROJECT_DIR" ]; then
    echo "备份当前版本..."
    timestamp=$(date +%Y%m%d_%H%M%S)
    tar -czf "$BACKUP_DIR/frontend_$timestamp.tar.gz" -C "$PROJECT_DIR" .
fi

# 更新代码
cd "$PROJECT_DIR"
git fetch origin
git checkout "$BRANCH"
git pull origin "$BRANCH"

# 安装依赖
echo "安装依赖..."
pnpm install

# 构建应用
echo "构建应用..."
pnpm build:antd

# 重启服务
echo "重启服务..."
sudo systemctl restart nginx

echo "部署完成!"

生产环境部署

高可用架构

1. 负载均衡配置

# /etc/nginx/nginx.conf
upstream aiogatro_backend {
    server 10.0.1.10:8080 weight=3;
    server 10.0.1.11:8080 weight=2;
    server 10.0.1.12:8080 weight=2;
    keepalive 32;
}

server {
    listen 80;
    server_name aiotagro.com www.aiotagro.com;
    
    # 重定向到 HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name aiotagro.com www.aiotagro.com;
    
    # SSL 配置
    ssl_certificate /etc/ssl/certs/aiotagro.crt;
    ssl_certificate_key /etc/ssl/private/aiotagro.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
    
    root /var/www/aiotagro/dist;
    index index.html;
    
    # 安全头
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    
    # 静态资源
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        add_header Vary Accept-Encoding;
    }
    
    # API 代理
    location /api/ {
        proxy_pass http://aiogatro_backend;
        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_cache_bypass $http_upgrade;
    }
    
    # SPA 路由
    location / {
        try_files $uri $uri/ /index.html;
    }
}

容器化部署

1. Docker 生产配置

# Dockerfile.prod
FROM node:18-alpine AS builder

WORKDIR /app

# 复制依赖文件
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile

# 复制源代码
COPY . .

# 构建应用
RUN pnpm build:antd

# 生产阶段
FROM nginx:alpine

# 复制构建结果
COPY --from=builder /app/dist /usr/share/nginx/html

# 复制 Nginx 配置
COPY nginx.conf /etc/nginx/nginx.conf

# 暴露端口
EXPOSE 80

# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]

2. Kubernetes 部署

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aiotagro-frontend
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: aiotagro-frontend
  template:
    metadata:
      labels:
        app: aiotagro-frontend
    spec:
      containers:
      - name: frontend
        image: aiotagro/frontend:latest
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: aiotagro-frontend-service
  namespace: production
spec:
  selector:
    app: aiotagro-frontend
  ports:
  - port: 80
    targetPort: 80
  type: LoadBalancer

自动化部署流程

1. CI/CD 配置

# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [ main ]
  workflow_dispatch:

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
      
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'pnpm'
        
    - name: Install dependencies
      run: pnpm install
      
    - name: Run tests
      run: pnpm test
      
    - name: Build application
      run: pnpm build:antd
      
    - name: Build Docker image
      run: |
        docker build -t $REGISTRY/$IMAGE_NAME:${{ github.sha }} .
        
    - name: Push Docker image
      run: |
        echo ${{ secrets.GITHUB_TOKEN }} | docker login $REGISTRY -u ${{ github.actor }} --password-stdin
        docker push $REGISTRY/$IMAGE_NAME:${{ github.sha }}
        
    - name: Deploy to production
      run: |
        # 部署到生产环境
        ssh deploy@production-server << EOF
          docker pull $REGISTRY/$IMAGE_NAME:${{ github.sha }}
          docker stop aiotagro-frontend || true
          docker rm aiotagro-frontend || true
          docker run -d --name aiotagro-frontend -p 80:80 $REGISTRY/$IMAGE_NAME:${{ github.sha }}
        EOF

监控和日志

1. 应用监控配置

// src/utils/monitoring.js
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals'

export const initMonitoring = () => {
  // 性能监控
  getCLS(console.log)
  getFID(console.log)
  getFCP(console.log)
  getLCP(console.log)
  getTTFB(console.log)
  
  // 错误监控
  window.addEventListener('error', (event) => {
    console.error('JavaScript Error:', event.error)
    // 发送到监控服务
    sendToMonitoringService({
      type: 'error',
      message: event.error.message,
      stack: event.error.stack,
      timestamp: new Date().toISOString()
    })
  })
  
  // 未处理的 Promise 拒绝
  window.addEventListener('unhandledrejection', (event) => {
    console.error('Unhandled Promise Rejection:', event.reason)
    sendToMonitoringService({
      type: 'promise_rejection',
      reason: event.reason,
      timestamp: new Date().toISOString()
    })
  })
}

const sendToMonitoringService = (data) => {
  // 发送到监控服务
  fetch('/api/monitoring', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  }).catch(console.error)
}

2. 日志配置

# Nginx 日志配置
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for" '
                'rt=$request_time uct="$upstream_connect_time" '
                'uht="$upstream_header_time" urt="$upstream_response_time"';

access_log /var/log/nginx/aiotagro-access.log main;
error_log /var/log/nginx/aiotagro-error.log warn;

备份和恢复

1. 备份策略

#!/bin/bash
# backup.sh

set -e

BACKUP_DIR="/opt/aiotagro/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="aiotagro_backup_$TIMESTAMP.tar.gz"

echo "开始备份 AIOTAGRO 系统..."

# 备份应用代码
tar -czf "$BACKUP_DIR/$BACKUP_FILE" \
  --exclude=node_modules \
  --exclude=dist \
  --exclude=.git \
  /opt/aiotagro/frontend

# 备份 Nginx 配置
tar -czf "$BACKUP_DIR/nginx_config_$TIMESTAMP.tar.gz" /etc/nginx

# 清理旧备份保留最近7天
find "$BACKUP_DIR" -name "aiotagro_backup_*.tar.gz" -mtime +7 -delete
find "$BACKUP_DIR" -name "nginx_config_*.tar.gz" -mtime +7 -delete

echo "备份完成: $BACKUP_DIR/$BACKUP_FILE"

2. 恢复策略

#!/bin/bash
# restore.sh

set -e

BACKUP_FILE="$1"

if [ -z "$BACKUP_FILE" ]; then
    echo "Usage: $0 <backup_file>"
    exit 1
fi

echo "开始恢复 AIOTAGRO 系统..."

# 停止服务
sudo systemctl stop nginx

# 恢复应用代码
tar -xzf "$BACKUP_FILE" -C /

# 恢复 Nginx 配置(可选)
# tar -xzf "nginx_config_*.tar.gz" -C /

# 启动服务
sudo systemctl start nginx

echo "恢复完成"

故障排除

常见问题

1. 构建失败

问题: pnpm build 失败 解决方案:

# 清理缓存
pnpm clean

# 重新安装依赖
pnpm install --force

# 重新构建
pnpm build:antd

2. Nginx 配置错误

问题: Nginx 启动失败 解决方案:

# 检查配置
sudo nginx -t

# 查看错误日志
sudo tail -f /var/log/nginx/error.log

3. 证书问题

问题: SSL 证书错误 解决方案:

# 检查证书权限
sudo chmod 600 /etc/ssl/private/aiotagro.key

# 重新加载 Nginx
sudo systemctl reload nginx

性能优化

1. 构建优化

// vite.config.js
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['vue', 'vue-router', 'pinia'],
          ui: ['ant-design-vue', '@ant-design/icons-vue'],
          utils: ['lodash', 'dayjs', 'axios']
        }
      }
    }
  }
})

2. 缓存策略

# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    add_header Vary Accept-Encoding;
}

# API 缓存
location /api/ {
    proxy_cache api_cache;
    proxy_cache_valid 200 302 5m;
    proxy_cache_valid 404 1m;
    add_header X-Cache-Status $upstream_cache_status;
}

安全配置

1. 安全头设置

# 安全头配置
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'";

2. 访问控制

# IP 限制
location /admin/ {
    allow 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
}

# 速率限制
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

location /api/ {
    limit_req zone=api burst=20 nodelay;
}

更新和维护

1. 定期更新

#!/bin/bash
# update.sh

set -e

echo "开始更新 AIOTAGRO 系统..."

# 更新代码
cd /opt/aiotagro/frontend
git pull origin main

# 更新依赖
pnpm install

# 构建应用
pnpm build:antd

# 重启服务
sudo systemctl restart nginx

echo "更新完成"

2. 健康检查

#!/bin/bash
# health-check.sh

set -e

URL="https://aiotagro.com"
TIMEOUT=10

response=$(curl -s -o /dev/null -w "%{http_code}" --max-time $TIMEOUT $URL)

if [ "$response" -eq 200 ]; then
    echo "健康检查通过: $URL"
    exit 0
else
    echo "健康检查失败: $URL (状态码: $response)"
    exit 1
fi

通过以上配置和脚本AIOTAGRO 管理系统可以实现稳定、安全、高效的部署和运维。