fix: Docker 构建改用 npm 替代 pnpm + 补全 OAuth/Redis 环境变量
- Dockerfile 全部改为 npm install + 全局 tsc,解决 pnpm 符号链接问题 - docker-compose 添加 Redis 服务、OAuth 环境变量透传、web 端口改为可配置 - MCP URL 改用 window.location.origin 适配反向代理 - tsconfig 添加 paths 映射解决 Docker 内模块引用 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
341
docs/deployment-guide.md
Normal file
341
docs/deployment-guide.md
Normal file
@@ -0,0 +1,341 @@
|
||||
# AgentFox 生产环境部署指南
|
||||
|
||||
## 架构概览
|
||||
|
||||
```
|
||||
┌──────────────────────────────────┐
|
||||
│ Docker Network │
|
||||
用户请求 │ │
|
||||
────────▶ ┌──────┴──────┐ │
|
||||
│ Nginx │ /api/* │
|
||||
│ (Web) │──────────▶┌─────────┐ │
|
||||
│ :80 │ │ Server │ │
|
||||
│ │ /mcp/* │ (API) │──┐ │
|
||||
│ SPA 静态 │──────▶┌───┤ :3000 │ │ │
|
||||
│ 资源服务 │ │ └─────────┘ │ │
|
||||
└─────────────┘ │ │ │
|
||||
│ ┌─────────┐ │ │
|
||||
└──▶│ MCP │ │ │
|
||||
│ :3001 │──┤ │
|
||||
└─────────┘ │ │
|
||||
▼ │
|
||||
┌────────────┐ ┌───────┐│
|
||||
│ PostgreSQL │ │ Redis ││
|
||||
│ :5432 │ │ :6379 ││
|
||||
└────────────┘ └───────┘│
|
||||
└──────────────────────────────────┘
|
||||
```
|
||||
|
||||
| 服务 | 镜像 | 端口 | 用途 |
|
||||
|------|------|------|------|
|
||||
| **web** | nginx:alpine | 80 | 前端 SPA + 反向代理(`/api/` → server,`/mcp/` → mcp) |
|
||||
| **server** | node:20-alpine | 3000 | Express API:认证、项目管理、OpenAPI 导入解析 |
|
||||
| **mcp** | node:20-alpine | 3001 | MCP 协议服务:为 LLM 提供 API 文档查询工具 |
|
||||
| **postgres** | postgres:16-alpine | 5432 | 主数据库:用户、项目、模块、端点数据 |
|
||||
| **redis** | redis:7-alpine | 6379 | 会话缓存、速率限制 |
|
||||
|
||||
**请求流向**:用户浏览器 → Nginx(:80) → 静态 SPA 或反代到 Server/MCP → PostgreSQL + Redis
|
||||
|
||||
---
|
||||
|
||||
## 前置要求
|
||||
|
||||
- Docker Engine 24+ 和 Docker Compose V2
|
||||
- 至少 2GB 内存、10GB 磁盘空间
|
||||
- 一个可访问的域名(用于 HTTPS 和 OAuth 回调)
|
||||
|
||||
---
|
||||
|
||||
## 第一步:获取代码
|
||||
|
||||
```bash
|
||||
git clone <repo-url> agent-fox
|
||||
cd agent-fox
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第二步:配置环境变量
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
编辑 `.env` 文件:
|
||||
|
||||
### 必填项
|
||||
|
||||
```bash
|
||||
# 先生成 3 个随机密钥
|
||||
openssl rand -hex 32 # → JWT_SECRET
|
||||
openssl rand -hex 32 # → JWT_REFRESH_SECRET
|
||||
openssl rand -hex 32 # → API_KEY_ENCRYPTION_SECRET
|
||||
```
|
||||
|
||||
```env
|
||||
JWT_SECRET=<粘贴第1个值>
|
||||
JWT_REFRESH_SECRET=<粘贴第2个值>
|
||||
API_KEY_ENCRYPTION_SECRET=<粘贴第3个值>
|
||||
```
|
||||
|
||||
> **警告**:这三个密钥一旦投入使用,切勿更换。更换 JWT_SECRET 会使所有已登录用户失效,更换 API_KEY_ENCRYPTION_SECRET 会使所有 API Key 不可用。
|
||||
|
||||
### 数据库(可选修改)
|
||||
|
||||
如需自定义数据库密码,同时修改 `docker-compose.yml` 和 `.env`:
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgresql://myuser:MyStr0ngP@ss@postgres:5432/agentfox
|
||||
```
|
||||
|
||||
对应修改 `docker-compose.yml` 中的 `POSTGRES_USER` / `POSTGRES_PASSWORD`。
|
||||
|
||||
### OAuth 第三方登录(可选)
|
||||
|
||||
不配置则仅支持邮箱密码注册登录。配置方法详见 [OAuth 注册指南](./oauth-setup-guide.md)。
|
||||
|
||||
```env
|
||||
# Google
|
||||
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
|
||||
GOOGLE_CLIENT_SECRET=GOCSPx-xxx
|
||||
|
||||
# GitHub
|
||||
GITHUB_CLIENT_ID=Ov23li...
|
||||
GITHUB_CLIENT_SECRET=xxx
|
||||
|
||||
# Apple
|
||||
APPLE_CLIENT_ID=com.example.agentfox
|
||||
APPLE_TEAM_ID=xxx
|
||||
APPLE_KEY_ID=xxx
|
||||
APPLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----
|
||||
|
||||
# 回调地址(必须与第三方平台注册的一致)
|
||||
OAUTH_CALLBACK_BASE_URL=https://你的域名
|
||||
FRONTEND_URL=https://你的域名
|
||||
```
|
||||
|
||||
### 完整 `.env` 示例
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgresql://agentfox:agentfox@postgres:5432/agentfox
|
||||
REDIS_URL=redis://redis:6379
|
||||
JWT_SECRET=e0c33a89e22b6ace23a1718d388e2b20f4735b5ab58c5cffe8d31c8fbedb6910
|
||||
JWT_REFRESH_SECRET=28f886e7af5b704b4c45440bd9db41706bf996601f78dd05ca98c7dce358c833
|
||||
API_KEY_ENCRYPTION_SECRET=5917b3fdc14565ede76b118d672dc98cdffb90f8ee16d88e5e6c61eb86e56eb8
|
||||
SERVER_PORT=3000
|
||||
MCP_PORT=3001
|
||||
MCP_BASE_URL=http://mcp:3001
|
||||
OAUTH_CALLBACK_BASE_URL=https://你的域名
|
||||
FRONTEND_URL=https://你的域名
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第三步:构建并启动
|
||||
|
||||
```bash
|
||||
docker compose up --build -d
|
||||
```
|
||||
|
||||
首次启动过程:
|
||||
1. Docker 构建 4 个镜像(约 3-5 分钟)
|
||||
2. PostgreSQL 和 Redis 率先启动并通过健康检查
|
||||
3. Server 启动时自动执行 `prisma migrate deploy` 创建数据库表
|
||||
4. MCP 和 Web 随后启动
|
||||
|
||||
### 验证
|
||||
|
||||
```bash
|
||||
# 确认 5 个服务全部 running
|
||||
docker compose ps
|
||||
|
||||
# 期望输出:
|
||||
# NAME STATUS
|
||||
# postgres Up (healthy)
|
||||
# redis Up (healthy)
|
||||
# server Up
|
||||
# mcp Up
|
||||
# web Up
|
||||
```
|
||||
|
||||
```bash
|
||||
# 验证 API 可达
|
||||
curl http://localhost/api/health
|
||||
|
||||
# 验证前端可达
|
||||
curl -s http://localhost | head -5
|
||||
```
|
||||
|
||||
访问 `http://服务器IP` 即可使用。
|
||||
|
||||
---
|
||||
|
||||
## 第四步:配置 HTTPS(生产必须)
|
||||
|
||||
### 方案 A:Caddy(推荐,自动 HTTPS)
|
||||
|
||||
```bash
|
||||
# 安装 Caddy
|
||||
sudo apt install -y caddy # Debian/Ubuntu
|
||||
# 或 brew install caddy # macOS
|
||||
```
|
||||
|
||||
创建 `/etc/caddy/Caddyfile`:
|
||||
|
||||
```
|
||||
你的域名 {
|
||||
reverse_proxy localhost:80
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo systemctl restart caddy
|
||||
```
|
||||
|
||||
Caddy 会自动申请和续期 Let's Encrypt 证书。
|
||||
|
||||
### 方案 B:修改 Nginx 配置
|
||||
|
||||
将 SSL 证书挂载进 web 容器,修改 `packages/web/nginx.conf` 添加 443 监听。
|
||||
|
||||
### 方案 C:云厂商负载均衡
|
||||
|
||||
将 HTTPS 终止放在云厂商 SLB/ALB 上,后端指向服务器的 80 端口。
|
||||
|
||||
---
|
||||
|
||||
## 生产加固清单
|
||||
|
||||
### 数据库安全
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
postgres:
|
||||
environment:
|
||||
POSTGRES_USER: agentfox_prod
|
||||
POSTGRES_PASSWORD: <使用 openssl rand -base64 24 生成>
|
||||
ports: [] # 生产环境移除端口映射,仅内部访问
|
||||
```
|
||||
|
||||
### Redis 安全
|
||||
|
||||
```yaml
|
||||
redis:
|
||||
command: redis-server --requirepass <密码>
|
||||
ports: [] # 生产环境移除端口映射
|
||||
```
|
||||
|
||||
对应更新环境变量:
|
||||
```env
|
||||
REDIS_URL=redis://:<密码>@redis:6379
|
||||
```
|
||||
|
||||
### 资源限制
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml 各服务添加
|
||||
server:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
cpus: "1.0"
|
||||
```
|
||||
|
||||
### 日志管理
|
||||
|
||||
```yaml
|
||||
# 防止日志文件无限增长
|
||||
services:
|
||||
server:
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 更新部署
|
||||
|
||||
```bash
|
||||
# 拉取最新代码
|
||||
git pull origin main
|
||||
|
||||
# 重新构建并重启(零停机:先构建再替换)
|
||||
docker compose up --build -d
|
||||
|
||||
# 如果只更新了前端
|
||||
docker compose build web && docker compose up -d web
|
||||
|
||||
# 如果只更新了后端
|
||||
docker compose build server && docker compose up -d server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据备份
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
```bash
|
||||
# 备份
|
||||
docker compose exec postgres pg_dump -U agentfox agentfox > backup_$(date +%Y%m%d).sql
|
||||
|
||||
# 恢复
|
||||
cat backup_20260403.sql | docker compose exec -T postgres psql -U agentfox agentfox
|
||||
```
|
||||
|
||||
### 定时备份(cron)
|
||||
|
||||
```bash
|
||||
# 每天凌晨 3 点备份
|
||||
0 3 * * * cd /path/to/agent-fox && docker compose exec -T postgres pg_dump -U agentfox agentfox | gzip > /backups/agentfox_$(date +\%Y\%m\%d).sql.gz
|
||||
```
|
||||
|
||||
### Redis
|
||||
|
||||
Redis 数据通过 `redisdata` volume 自动持久化(RDB 快照)。
|
||||
|
||||
---
|
||||
|
||||
## 常用运维命令
|
||||
|
||||
```bash
|
||||
# === 服务管理 ===
|
||||
docker compose up -d # 启动
|
||||
docker compose down # 停止
|
||||
docker compose restart server # 重启单个服务
|
||||
docker compose logs -f server # 查看日志(实时)
|
||||
docker compose logs --tail 100 # 最近 100 行
|
||||
|
||||
# === 调试 ===
|
||||
docker compose exec server sh # 进入 server 容器
|
||||
docker compose exec postgres psql -U agentfox # 进入数据库
|
||||
docker compose exec redis redis-cli # 进入 Redis
|
||||
|
||||
# === 数据库 ===
|
||||
docker compose exec server npx prisma migrate deploy --schema=prisma/schema.prisma # 手动迁移
|
||||
docker compose exec postgres psql -U agentfox -c "\dt" # 查看表
|
||||
docker compose exec postgres psql -U agentfox -c "SELECT count(*) FROM \"User\"" # 查询用户数
|
||||
|
||||
# === 清理 ===
|
||||
docker compose down -v # ⚠️ 停止并删除所有数据
|
||||
docker system prune -f # 清理无用镜像/缓存
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 故障排查
|
||||
|
||||
| 现象 | 原因 & 解决 |
|
||||
|------|------------|
|
||||
| `docker compose up` 后 server 一直重启 | 查看 `docker compose logs server`,通常是数据库连接失败。确认 postgres 已 healthy |
|
||||
| 访问页面显示 502 | server 或 mcp 未正常运行。`docker compose ps` 检查状态 |
|
||||
| 登录报 500 | 检查 `JWT_SECRET` 是否已正确配置,`docker compose logs server` 查看详情 |
|
||||
| OAuth 回调报错 | 确认 `.env` 中 `OAUTH_CALLBACK_BASE_URL` 与第三方平台注册的回调地址完全一致(协议+域名) |
|
||||
| MCP 工具连接失败 | 1) 确认 API Key 正确 2) `docker compose logs mcp` 查看错误 3) 确认 MCP URL 格式为 `http(s)://域名/mcp/<projectId>` |
|
||||
| Redis 连接失败 | `docker compose exec redis redis-cli ping` 应返回 PONG |
|
||||
| 数据库迁移失败 | `docker compose exec server npx prisma migrate deploy --schema=prisma/schema.prisma` 手动执行并查看报错 |
|
||||
| 磁盘空间不足 | `docker system prune -f` 清理无用镜像,检查 pg 数据量 |
|
||||
105
docs/oauth-setup-guide.md
Normal file
105
docs/oauth-setup-guide.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# OAuth 第三方登录注册指南
|
||||
|
||||
## 1. Google OAuth
|
||||
|
||||
**前往**: [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
|
||||
|
||||
**步骤**:
|
||||
1. 创建项目(或选已有项目)
|
||||
2. 左侧菜单 → "OAuth consent screen" → 选 External → 填写应用名称(AgentFox)、用户支持邮箱
|
||||
3. 左侧菜单 → "Credentials" → "Create Credentials" → "OAuth 2.0 Client ID"
|
||||
4. 应用类型选 **Web application**
|
||||
5. 名称填 `AgentFox Web`
|
||||
6. "Authorized redirect URIs" 添加:
|
||||
- 开发:`http://localhost:3000/api/auth/oauth/google/callback`
|
||||
- 生产:`https://你的域名/api/auth/oauth/google/callback`
|
||||
7. 创建后拿到 **Client ID** 和 **Client Secret**
|
||||
|
||||
**写入 `.env`**:
|
||||
```
|
||||
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
|
||||
GOOGLE_CLIENT_SECRET=GOCSPx-xxx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. GitHub OAuth
|
||||
|
||||
**前往**: [GitHub Developer Settings](https://github.com/settings/developers)
|
||||
|
||||
**步骤**:
|
||||
1. "OAuth Apps" → "New OAuth App"
|
||||
2. 填写:
|
||||
- Application name: `AgentFox`
|
||||
- Homepage URL: `http://localhost:5173`(开发)
|
||||
- Authorization callback URL: `http://localhost:3000/api/auth/oauth/github/callback`
|
||||
3. 创建后拿到 **Client ID**,点击 "Generate a new client secret" 拿到 **Client Secret**
|
||||
|
||||
**写入 `.env`**:
|
||||
```
|
||||
GITHUB_CLIENT_ID=Ov23li...
|
||||
GITHUB_CLIENT_SECRET=xxx
|
||||
```
|
||||
|
||||
> 生产环境需要再创建一个 OAuth App,callback URL 改为生产域名。
|
||||
|
||||
---
|
||||
|
||||
## 3. Apple Sign In
|
||||
|
||||
> 需要 **Apple Developer Program** 付费账号($99/年)。如果暂时没有,可以先跳过,按钮已在前端显示但会报错提示。
|
||||
|
||||
**前往**: [Apple Developer - Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources)
|
||||
|
||||
### 3a. 注册 App ID
|
||||
1. "Identifiers" → "+" → 选 "App IDs" → "App"
|
||||
2. Description: `AgentFox`
|
||||
3. Bundle ID: `com.agentfox.web`(Explicit)
|
||||
4. 勾选 "Sign In with Apple" → Continue → Register
|
||||
|
||||
### 3b. 创建 Services ID
|
||||
1. "Identifiers" → "+" → 选 "Services IDs"
|
||||
2. Description: `AgentFox Web Login`
|
||||
3. Identifier: `com.agentfox.web.login` ← 这就是 **APPLE_CLIENT_ID**
|
||||
4. 勾选 "Sign In with Apple" → Configure:
|
||||
- Primary App ID: 选上面创建的 App ID
|
||||
- Domains: `你的域名`(开发时用 ngrok)
|
||||
- Return URLs: `https://你的域名/api/auth/oauth/apple/callback`
|
||||
5. Save → Continue → Register
|
||||
|
||||
### 3c. 创建 Key
|
||||
1. "Keys" → "+" → 名称 `AgentFox Auth Key`
|
||||
2. 勾选 "Sign In with Apple" → Configure → 选 Primary App ID → Save
|
||||
3. Continue → Register → **下载 .p8 文件**(只能下载一次!)
|
||||
4. 记下 **Key ID**
|
||||
|
||||
### 3d. 找到 Team ID
|
||||
1. 右上角账户名 → "Membership details"
|
||||
2. 记下 **Team ID**
|
||||
|
||||
**写入 `.env`**:
|
||||
```
|
||||
APPLE_CLIENT_ID=com.agentfox.web.login
|
||||
APPLE_TEAM_ID=XXXXXXXXXX
|
||||
APPLE_KEY_ID=XXXXXXXXXX
|
||||
APPLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIGT...这里是.p8文件内容...\n-----END PRIVATE KEY-----"
|
||||
```
|
||||
|
||||
> Apple 回调必须 HTTPS。本地开发可以用 `ngrok http 3000` 获取临时 HTTPS 域名,然后设置 `OAUTH_CALLBACK_BASE_URL=https://xxx.ngrok.io`。
|
||||
|
||||
---
|
||||
|
||||
## 通用配置
|
||||
|
||||
`.env` 中还需要设置回调基础 URL:
|
||||
|
||||
```
|
||||
OAUTH_CALLBACK_BASE_URL=http://localhost:3000
|
||||
FRONTEND_URL=http://localhost:5173
|
||||
```
|
||||
|
||||
生产环境改为实际域名即可。
|
||||
|
||||
## 验证
|
||||
|
||||
配置好后启动 `pnpm dev:server` + `pnpm dev:web`,访问 `/login` 页面点击对应按钮即可测试。
|
||||
Reference in New Issue
Block a user