11 KiB
11 KiB
运维与部署模块
服务器与基础设施
环境信息
- 域名: 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 volumezhuiguang_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)
开发规则引用
运维和部署必须遵守以下规则:
- 第十四章 - Docker容器规范:容器清单(app+cron)、host网络、健康检查、容器管理命令
- 第十五章 - 部署规范:部署前5项自检、构建流程、部署后六项验证、镜像回滚策略
- 第八章 - 定时任务规范:crontab管理四方同步、entrypoint-cron信号处理、备份脚本完整性
- 第十三章 - Shell脚本规范:set -e、结构化输出、磁盘预检、禁止操作(禁杀共享进程)
- 第十九章 - 环境变量管理规范:变量分级、.env.example同步、脚本侧加载顺序