# 部署文档 ## 部署概述 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. 环境准备 ```bash # 安装 Node.js # 访问 https://nodejs.org/ 下载安装包 # 安装 pnpm npm install -g pnpm # 验证安装 node --version pnpm --version ``` #### 2. 项目初始化 ```bash # 克隆项目 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 # 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 配置 ```yaml # 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. 启动服务 ```bash # 构建并启动服务 docker-compose -f docker-compose.dev.yml up --build # 后台运行 docker-compose -f docker-compose.dev.yml up -d ``` ## 测试环境部署 ### 手动部署 #### 1. 服务器准备 ```bash # 登录服务器 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. 环境配置 ```bash # 安装 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. 构建应用 ```bash # 构建生产版本 pnpm build:antd # 检查构建结果 ls -la dist/ ``` #### 4. 配置 Nginx ```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. 启用站点 ```bash # 创建符号链接 sudo ln -s /etc/nginx/sites-available/aiotagro-test /etc/nginx/sites-enabled/ # 测试配置 sudo nginx -t # 重启 Nginx sudo systemctl restart nginx ``` ### 自动化部署脚本 ```bash #!/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. 负载均衡配置 ```nginx # /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 # 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 部署 ```yaml # 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 配置 ```yaml # .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. 应用监控配置 ```javascript // 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 # 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. 备份策略 ```bash #!/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. 恢复策略 ```bash #!/bin/bash # restore.sh set -e BACKUP_FILE="$1" if [ -z "$BACKUP_FILE" ]; then echo "Usage: $0 " 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 失败 **解决方案**: ```bash # 清理缓存 pnpm clean # 重新安装依赖 pnpm install --force # 重新构建 pnpm build:antd ``` #### 2. Nginx 配置错误 **问题**: Nginx 启动失败 **解决方案**: ```bash # 检查配置 sudo nginx -t # 查看错误日志 sudo tail -f /var/log/nginx/error.log ``` #### 3. 证书问题 **问题**: SSL 证书错误 **解决方案**: ```bash # 检查证书权限 sudo chmod 600 /etc/ssl/private/aiotagro.key # 重新加载 Nginx sudo systemctl reload nginx ``` ## 性能优化 ### 1. 构建优化 ```javascript // 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. 缓存策略 ```nginx # 静态资源缓存 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. 安全头设置 ```nginx # 安全头配置 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. 访问控制 ```nginx # 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. 定期更新 ```bash #!/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. 健康检查 ```bash #!/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 管理系统可以实现稳定、安全、高效的部署和运维。