Files
zhuiguang-ai/.trae/specs/modules/09-devops.md
T

11 KiB
Raw Blame History

运维与部署模块

服务器与基础设施

环境信息

  • 域名: www.zhuig.com (HTTPS,SSL证书自动续期)
  • 云服务器: 119.45.242.239 (登录名: ubuntu, 密钥: C:\SGP_KF\ZhuiGuangAI\zhuiguang-ai\Pem\zg.pem)
  • 数据库: 阿里云RDS MySQL — rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306
  • Redis: Docker容器 redis-cache:6379,有密码认证(共享服务)
  • Nacos: Docker容器 nacos:8848(共享服务)
  • MinIO: Docker容器 minio:9000(共享服务)
  • 部署目录: /home/ubuntu/zhuiguang-ai
  • 访问地址: https://www.zhuig.com (HTTP自动跳转HTTPS)
  • 本地Git同步目录: C:\gitbf

端口规范

  • 应用端口范围: 8301-8310(预留扩展)
  • 默认端口: 8301
  • 强制要求: 本项目端口必须锁定在8301-8310区间内,禁止使用其他端口

容器化部署架构

容器清单

容器名 镜像 端口 用途
zhuiguang-ai-app zhuiguang-ai:latest 8301 Next.js 应用服务
zhuiguang-ai-cron zhuiguang-ai:latest 8310 (prometheus) supercronic 定时任务调度

命名卷

卷名 挂载点 用途
zhuiguang_ai_bot_data /app/data 应用数据(bot-characters.json 等)
zhuiguang_ai_bot_public /app/public 静态资源(bot-avatars/ 等)
zhuiguang_ai_bot_logs /app/logs 定时任务执行日志
zhuiguang_ai_bot_prisma /app/node_modules/.prisma Prisma 生成文件

网络模式

  • host 网络: 容器直接使用宿主机网络栈,通过 localhost 访问共享服务(Redis:6379、Nacos:8848、MinIO:9000)

架构图

Nginx (443) → 127.0.0.1:8301 → zhuiguang-ai-app (Docker, host 网络)
Cron → zhuiguang-ai-cron (Docker, supercronic, host 网络)
共享卷: data / public / logs / prisma (命名卷)
外部: 阿里云 RDS / 共享 Redis / 共享 Nacos / 共享 MinIO

Nginx配置

  • 文件: /etc/nginx/sites-enabled/zhuiguang-ai
  • HTTPS反向代理到本地8301端口
  • HTTP自动跳转HTTPS
  • SSL证书自动续期
  • 注意: Nginx 始终代理 127.0.0.1:8301,切换 PM2→Docker 时无需改动

部署流程

本地开发

# 1. 安装依赖
npm install

# 2. 配置环境变量
# 编辑 .env 文件

# 3. 数据库迁移
npx prisma migrate dev

# 4. 启动开发服务器
npm run dev

生产构建 + 部署

# 1. 构建镜像
cd /home/ubuntu/zhuiguang-ai
docker build -t zhuiguang-ai:latest .

# 2. 停止旧容器
docker stop zhuiguang-ai-app zhuiguang-ai-cron
docker rm zhuiguang-ai-app zhuiguang-ai-cron

# 3. 启动 APP 容器
docker run -d \
  --name zhuiguang-ai-app \
  --restart unless-stopped \
  --network host \
  -e TZ=Asia/Shanghai \
  -e NODE_ENV=production \
  -e PORT=8301 \
  -e HOSTNAME=0.0.0.0 \
  -v /home/ubuntu/zhuiguang-ai/env/.env.production:/app/.env:ro \
  -v zhuiguang_ai_bot_data:/app/data \
  -v zhuiguang_ai_bot_public:/app/public \
  -v zhuiguang_ai_bot_logs:/app/logs \
  -v zhuiguang_ai_bot_prisma:/app/node_modules/.prisma \
  zhuiguang-ai:latest

# 4. 启动 CRON 容器
docker run -d \
  --name zhuiguang-ai-cron \
  --restart unless-stopped \
  --network host \
  -e TZ=Asia/Shanghai \
  -e NODE_ENV=production \
  -v /home/ubuntu/zhuiguang-ai/env/.env.production:/app/.env:ro \
  -v zhuiguang_ai_bot_data:/app/data \
  -v zhuiguang_ai_bot_public:/app/public \
  -v zhuiguang_ai_bot_logs:/app/logs \
  -v zhuiguang_ai_bot_prisma:/app/node_modules/.prisma \
  -v /home/ubuntu/zhuiguang-ai/crontab.txt:/app/crontab.txt:ro \
  zhuiguang-ai:latest /usr/local/bin/entrypoint-cron.sh

# 5. 验证
docker ps --filter name=zhuiguang-ai
curl -I http://localhost:8301/

使用 docker-compose(推荐)

cd /home/ubuntu/zhuiguang-ai
docker-compose down
docker-compose build
docker-compose up -d

测试部署(端口 8302,与生产并行)

cd /home/ubuntu/zhuiguang-ai
docker-compose -f docker-compose.test.yml down
docker-compose -f docker-compose.test.yml build
docker-compose -f docker-compose.test.yml up -d

Docker 镜像构建

Dockerfile 结构

阶段 1: deps  — npm ci 安装依赖(含 devDependencies)
阶段 2: builder — prisma generate + npm run build
阶段 3: runner — 仅复制生产依赖 + 构建产物,最终镜像 ~1.27GB

构建优化

  • aliyun 镜像源: apk 和 npm 均切换国内源,加速安装
  • supercronic 预下载: 二进制文件 scripts/bin/supercronic-linux-amd64 预下载到仓库,避免 GitHub release 下载超时
  • layer cache: 依赖层变化少,重复构建时利用缓存

Build 期注意事项

  • Prisma 7 要求 datasource.url 在 prisma.config.ts 中,不能在 schema.prisma 中
  • Next.js build 期会求值 server page/API route,依赖 env 变量的模块需加 export const dynamic = "force-dynamic"
  • OpenAI SDK v6+ 构造时校验 API key,需懒加载

定时任务(Supercronic 容器调度)

调度方式

  • 不再使用主机 crontab + cron-wrapper.sh
  • 由 zhuiguang-ai-cron 容器内 supercronic 调度
  • 配置文件: crontab.txt(项目根目录)
  • 修改 crontab.txt 后需重建 cron 容器生效

任务列表(25 条)

时间 任务 脚本
01:00 Task5 更新星值 scripts/task5-update-stars.mjs
02:00 Bot 技能结晶 scripts/bot-skill-crystallize.mjs
03:00 Task3 工具巡检 scripts/task3-check-tools.mjs
04:00 Task6 评测热门 scripts/task6-review-hot.mjs
05:00 Bot 亲和度与画像 scripts/bot-affinity-update.mjs
05:00 Task4 发现技能 scripts/daily-discover.mjs
06:00 Task1 发现工具 scripts/task1-discover-tools.mjs
07:30 AI日报 scripts/daily-news.mjs
08:00 Task7 新闻推社区 scripts/task7-news-to-community.mjs
09:00-23:00 Bot 活动引擎 scripts/bot-activity.mjs(每小时)
21:30 Bot 反馈闭环 scripts/bot-feedback-loop.mjs
周日 22:30 Bot 跨板块亲和度 scripts/bot-affinity-update.mjs
周日 02:00 Bot 周度复盘 scripts/bot-weekly-review.mjs

日志目录

  • 容器内路径: /app/logs/(挂载到 Docker volume zhuiguang_ai_bot_logs)
  • 查看日志: docker logs zhuiguang-ai-cron 或 docker exec zhuiguang-ai-cron cat /app/logs/bot-activity.log

容器运维命令

状态查看

# 容器状态
docker ps --filter name=zhuiguang-ai

# 容器健康状态
docker inspect zhuiguang-ai-app --format '{{.State.Health.Status}}'

# 端口占用
ss -tlnp | grep 8301

# 卷列表
docker volume ls --filter name=zhuiguang_ai

日志查看

# APP 容器日志
docker logs --tail 50 zhuiguang-ai-app
docker logs -f zhuiguang-ai-app    # 实时跟踪

# CRON 容器日志
docker logs --tail 50 zhuiguang-ai-cron

# 查看容器内定时任务日志
docker exec zhuiguang-ai-cron ls -la /app/logs/
docker exec zhuiguang-ai-cron tail -50 /app/logs/bot-activity.log

重启

# 重启 APP 容器
docker restart zhuiguang-ai-app

# 重启 CRON 容器(修改 crontab.txt 后)
docker restart zhuiguang-ai-cron

进入容器调试

docker exec -it zhuiguang-ai-app sh
docker exec -it zhuiguang-ai-cron sh

卷备份

备份脚本

  • scripts/backup-volumes.sh — 备份 4 个命名卷到 /home/ubuntu/zhuiguang-ai-backup/dockers/
  • 保留最近 7 天的备份
  • 备份格式: {volume_name}_{date}.tar.gz

主机备份 cron

  • scripts/install-cron-backup.sh — 安装主机备份 cron(每天 03:00)
  • 备份目录: /home/ubuntu/zhuiguang-ai-backup/dockers/

环境变量

.env.production 配置

# 数据库(必填)
DATABASE_URL="mysql://mohe001:***@rm-0jlbgr2rv6dj3t6jngo.mysql.rds.aliyuncs.com:3306/zhuiguang_ai?charset=utf8mb4"

# NextAuth(必填)
NEXTAUTH_URL="http://localhost:8301"
NEXTAUTH_SECRET="请生成一个随机高强度密钥(至少32位)"

# GitHub API(必填,提升限流60→5000次/小时)
GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"

# DeepSeek API(必填)
DEEPSEEK_API_KEY="sk-..."
DEEPSEEK_MODEL="deepseek-v4-pro"

# OpenAI API(Bot 活动引擎使用)
OPENAI_API_KEY="sk-..."

注意: 容器运行时 .env 文件以只读方式挂载(:ro),避免容器内误修改。


安全配置

HTTP 响应头

next.config.mjs 配置以下安全响应头:

  • CSP (Content-Security-Policy): default-src 'self' + 安全白名单
  • HSTS (Strict-Transport-Security): max-age=31536000; includeSubDomains
  • Permissions-Policy: camera=(), microphone=(), geolocation=()
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • X-XSS-Protection: 1; mode=block
  • Referrer-Policy: strict-origin-when-cross-origin

权限控制

  • middleware.ts 中 /admin/* 和 /api/admin/* 仅 admin 角色可访问(VIP 用户无权限)

踩坑记录

  • Next.js 14不支持useActionState,登录页用原生表单POST
  • Prisma MariaDB adapter需要连接字符串方式初始化
  • 图片域名需在next.config.mjs中配置remotePatterns
  • 热重载后需清除.next缓存: 删除.next目录后重启
  • Chart.js组件需用dynamic import + ssr: false,不支持服务端渲染
  • Prisma 7.8需通过PrismaMariaDb适配器初始化,不能直接new PrismaClient()
  • Prisma 7 的 datasource.url 必须放在 prisma.config.ts 中,不能在 schema.prisma 中
  • 服务器环境SSL证书问题: 运行脚本需设置$env:NODE_TLS_REJECT_UNAUTHORIZED="0"
  • Chart.js font.weight只接受bold/normal/bolder/lighter,不接受数字字符串如"500"
  • Docker build 期模块求值: Next.js build 时会预渲染 server page 和 API route,导致 Prisma/OpenAI 等模块被求值。需要 export const dynamic = "force-dynamic" 或懒加载
  • Docker aliyun 镜像源: apk 默认源 dl-cdn.alpinelinux.org 极慢(1m23s),切换 mirrors.aliyun.com 仅需 0.134s;npm 切换 registry.npmmirror.com
  • Supercronic 下载: GitHub release 的 release-assets.githubusercontent.com 在服务器上可能超时,建议预下载二进制到仓库
  • Docker host 网络: 使用 host 网络模式才能让容器内进程通过 localhost 访问共享服务(Redis、Nacos、MinIO)

开发规则引用

运维和部署必须遵守以下规则: