From 5e6efdaf5977337aab8c8dcd76a51cb8d3697cde Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 3 Apr 2026 17:24:52 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Docker=20=E6=9E=84=E5=BB=BA=E6=94=B9?= =?UTF-8?q?=E7=94=A8=20npm=20=E6=9B=BF=E4=BB=A3=20pnpm=20+=20=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=20OAuth/Redis=20=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .dockerignore | 6 + docker-compose.dev.yml | 10 +- docker-compose.yml | 27 +- docs/deployment-guide.md | 341 ++++++++++++++++++ docs/oauth-setup-guide.md | 105 ++++++ packages/mcp/Dockerfile | 45 ++- packages/mcp/tsconfig.json | 6 +- packages/server/Dockerfile | 47 ++- .../server/src/services/openapi-parser.ts | 2 +- packages/server/tsconfig.json | 6 +- packages/web/Dockerfile | 18 +- .../web/src/pages/tabs/McpIntegration.tsx | 3 +- 12 files changed, 553 insertions(+), 63 deletions(-) create mode 100644 .dockerignore create mode 100644 docs/deployment-guide.md create mode 100644 docs/oauth-setup-guide.md diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..dd968c3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +node_modules +.worktrees +.claude +.git +*.md +!README.md diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index dc209dc..96d0757 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -3,11 +3,15 @@ services: ports: - "5432:5432" + redis: + ports: + - "6379:6379" + server: build: context: . dockerfile: packages/server/Dockerfile - target: deps + target: build extra_hosts: - "host.docker.internal:host-gateway" command: > @@ -24,6 +28,7 @@ services: - ./prisma:/app/prisma environment: DATABASE_URL: postgresql://agentfox:agentfox@postgres:5432/agentfox + REDIS_URL: redis://redis:6379 JWT_SECRET: dev-secret JWT_REFRESH_SECRET: dev-refresh-secret SERVER_PORT: "3000" @@ -33,7 +38,7 @@ services: build: context: . dockerfile: packages/mcp/Dockerfile - target: deps + target: build command: > sh -c " npx prisma generate --schema=prisma/schema.prisma && @@ -48,6 +53,7 @@ services: - ./prisma:/app/prisma environment: DATABASE_URL: postgresql://agentfox:agentfox@postgres:5432/agentfox + REDIS_URL: redis://redis:6379 MCP_PORT: "3001" NODE_ENV: development diff --git a/docker-compose.yml b/docker-compose.yml index a46cc9e..409b903 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,21 +15,42 @@ services: timeout: 5s retries: 5 + redis: + image: redis:7-alpine + ports: + - "6379:6379" + volumes: + - redisdata:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 5 + server: build: context: . dockerfile: packages/server/Dockerfile environment: DATABASE_URL: postgresql://agentfox:agentfox@postgres:5432/agentfox + REDIS_URL: redis://redis:6379 JWT_SECRET: ${JWT_SECRET:-change-me-in-production} JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-change-me-refresh-in-production} API_KEY_ENCRYPTION_SECRET: ${API_KEY_ENCRYPTION_SECRET:-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef} + GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-} + GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-} + GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-} + GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-} + OAUTH_CALLBACK_BASE_URL: ${OAUTH_CALLBACK_BASE_URL:-} + FRONTEND_URL: ${FRONTEND_URL:-} SERVER_PORT: "3000" ports: - "3000:3000" depends_on: postgres: condition: service_healthy + redis: + condition: service_healthy mcp: build: @@ -37,22 +58,26 @@ services: dockerfile: packages/mcp/Dockerfile environment: DATABASE_URL: postgresql://agentfox:agentfox@postgres:5432/agentfox + REDIS_URL: redis://redis:6379 MCP_PORT: "3001" ports: - "3001:3001" depends_on: postgres: condition: service_healthy + redis: + condition: service_healthy web: build: context: . dockerfile: packages/web/Dockerfile ports: - - "80:80" + - "${WEB_PORT:-8088}:80" depends_on: - server - mcp volumes: pgdata: + redisdata: diff --git a/docs/deployment-guide.md b/docs/deployment-guide.md new file mode 100644 index 0000000..cb5e75e --- /dev/null +++ b/docs/deployment-guide.md @@ -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 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/` | +| 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 数据量 | diff --git a/docs/oauth-setup-guide.md b/docs/oauth-setup-guide.md new file mode 100644 index 0000000..6917e26 --- /dev/null +++ b/docs/oauth-setup-guide.md @@ -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` 页面点击对应按钮即可测试。 diff --git a/packages/mcp/Dockerfile b/packages/mcp/Dockerfile index a2f4481..421f2fd 100644 --- a/packages/mcp/Dockerfile +++ b/packages/mcp/Dockerfile @@ -1,36 +1,35 @@ -FROM node:20-alpine AS base -RUN corepack enable && corepack prepare pnpm@latest --activate +FROM node:20-alpine AS build +RUN npm install -g typescript@5 WORKDIR /app -FROM base AS deps -COPY pnpm-lock.yaml pnpm-workspace.yaml package.json tsconfig.base.json ./ -COPY packages/shared/package.json packages/shared/ -COPY packages/shared/tsconfig.json packages/shared/ -COPY packages/mcp/package.json packages/mcp/ -COPY packages/mcp/tsconfig.json packages/mcp/ -COPY prisma/ prisma/ -RUN pnpm install --frozen-lockfile - -FROM base AS build -COPY --from=deps /app/ ./ -COPY packages/shared/ packages/shared/ -COPY packages/mcp/ packages/mcp/ -COPY prisma/ prisma/ COPY tsconfig.base.json ./ -RUN npx prisma generate --schema=prisma/schema.prisma -RUN pnpm --filter @agent-fox/shared build -RUN pnpm --filter @agent-fox/mcp build +COPY prisma/ prisma/ +# shared: 安装依赖 + prisma generate +COPY packages/shared/package.json packages/shared/tsconfig.json packages/shared/ +RUN cd packages/shared && npm install && npx prisma generate --schema=../../prisma/schema.prisma + +# mcp: 安装依赖(workspace:* → file: 引用) +COPY packages/mcp/package.json packages/mcp/tsconfig.json packages/mcp/ +RUN cd packages/mcp && sed -i 's|"workspace:\*"|"file:../shared"|g' package.json && npm install + +# 拷贝源码 + 编译 +COPY packages/shared/src/ packages/shared/src/ +COPY packages/mcp/src/ packages/mcp/src/ + +RUN tsc -p packages/shared/tsconfig.json +RUN tsc -p packages/mcp/tsconfig.json + +# --- 精简运行时镜像 --- FROM node:20-alpine AS runtime WORKDIR /app -COPY --from=build /app/node_modules ./node_modules + COPY --from=build /app/packages/shared/dist ./packages/shared/dist -COPY --from=build /app/packages/shared/node_modules ./packages/shared/node_modules COPY --from=build /app/packages/shared/package.json ./packages/shared/ +COPY --from=build /app/packages/shared/node_modules ./packages/shared/node_modules COPY --from=build /app/packages/mcp/dist ./packages/mcp/dist -COPY --from=build /app/packages/mcp/node_modules ./packages/mcp/node_modules COPY --from=build /app/packages/mcp/package.json ./packages/mcp/ -COPY --from=build /app/prisma ./prisma +COPY --from=build /app/packages/mcp/node_modules ./packages/mcp/node_modules WORKDIR /app/packages/mcp EXPOSE 3001 diff --git a/packages/mcp/tsconfig.json b/packages/mcp/tsconfig.json index 5a24989..351756c 100644 --- a/packages/mcp/tsconfig.json +++ b/packages/mcp/tsconfig.json @@ -2,7 +2,11 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "dist", - "rootDir": "src" + "rootDir": "src", + "baseUrl": ".", + "paths": { + "@agent-fox/shared": ["../shared/dist"] + } }, "include": ["src"] } diff --git a/packages/server/Dockerfile b/packages/server/Dockerfile index 3aae8ab..d6e0e07 100644 --- a/packages/server/Dockerfile +++ b/packages/server/Dockerfile @@ -1,40 +1,39 @@ -FROM node:20-alpine AS base -RUN corepack enable && corepack prepare pnpm@latest --activate +FROM node:20-alpine AS build +RUN npm install -g typescript@5 WORKDIR /app -FROM base AS deps -COPY pnpm-lock.yaml pnpm-workspace.yaml package.json tsconfig.base.json ./ -COPY packages/shared/package.json packages/shared/ -COPY packages/shared/tsconfig.json packages/shared/ -COPY packages/server/package.json packages/server/ -COPY packages/server/tsconfig.json packages/server/ -COPY prisma/ prisma/ -RUN pnpm install --frozen-lockfile - -FROM base AS build -COPY --from=deps /app/ ./ -COPY packages/shared/ packages/shared/ -COPY packages/server/ packages/server/ -COPY prisma/ prisma/ COPY tsconfig.base.json ./ -RUN npx prisma generate --schema=prisma/schema.prisma -RUN pnpm --filter @agent-fox/shared build -RUN pnpm --filter @agent-fox/server build +COPY prisma/ prisma/ +# shared: 安装依赖 + prisma generate +COPY packages/shared/package.json packages/shared/tsconfig.json packages/shared/ +RUN cd packages/shared && npm install && npx prisma generate --schema=../../prisma/schema.prisma + +# server: 安装依赖(workspace:* → file: 引用) +COPY packages/server/package.json packages/server/tsconfig.json packages/server/ +RUN cd packages/server && sed -i 's|"workspace:\*"|"file:../shared"|g' package.json && npm install + +# 拷贝源码 + 编译 +COPY packages/shared/src/ packages/shared/src/ +COPY packages/server/src/ packages/server/src/ + +RUN tsc -p packages/shared/tsconfig.json +RUN tsc -p packages/server/tsconfig.json + +# --- 精简运行时镜像 --- FROM node:20-alpine AS runtime +RUN npm install -g prisma@6 WORKDIR /app -COPY --from=build /app/node_modules ./node_modules + COPY --from=build /app/packages/shared/dist ./packages/shared/dist -COPY --from=build /app/packages/shared/node_modules ./packages/shared/node_modules COPY --from=build /app/packages/shared/package.json ./packages/shared/ +COPY --from=build /app/packages/shared/node_modules ./packages/shared/node_modules COPY --from=build /app/packages/server/dist ./packages/server/dist -COPY --from=build /app/packages/server/node_modules ./packages/server/node_modules COPY --from=build /app/packages/server/package.json ./packages/server/ +COPY --from=build /app/packages/server/node_modules ./packages/server/node_modules COPY --from=build /app/prisma ./prisma COPY scripts/migrate-and-start.sh ./scripts/ - RUN chmod +x scripts/migrate-and-start.sh -RUN npm install -g prisma@6 EXPOSE 3000 CMD ["sh", "scripts/migrate-and-start.sh"] diff --git a/packages/server/src/services/openapi-parser.ts b/packages/server/src/services/openapi-parser.ts index 452b687..50a85e4 100644 --- a/packages/server/src/services/openapi-parser.ts +++ b/packages/server/src/services/openapi-parser.ts @@ -122,7 +122,7 @@ export async function parseOpenApiDocument(input: string | object): Promise(null); const { onOpenSettings } = useLayoutContext(); const { t } = useI18n(); - const mcpHost = window.location.hostname; - const mcpUrl = `http://${mcpHost}:3001/mcp/${project.id}`; + const mcpUrl = `${window.location.origin}/mcp/${project.id}`; const { data: keyStatus } = useQuery({ queryKey: ['api-key-status'],