feat: 将项目从nano重命名为beaver并更新相关配置
- 将所有环境变量前缀从NANO_改为BEAVER_ - 更新README.md文档内容,包括项目介绍、组件说明和快速开始指南 - 修改.gitignore文件,添加auth-portal运行时路径排除规则 - 更新app-instance镜像标签从nano/app-instance改为beaver/app-instance - 增强技能安全检查器,支持工具前缀白名单功能 - 添加技能草稿重新检查安全性API端点 - 扩展证据选择器,收集工具调用名称用于技能学习 - 改进技能合成器,基于实际调用的工具生成工具提示 - 优化路由超时处理机制,增加重试逻辑 - 更新后端架构文档,添加可视化入口和基础概念说明 - 实现在WebSocket消息中传递工具迭代次数信息
This commit is contained in:
686
部署指南.md
686
部署指南.md
@ -1,42 +1,29 @@
|
||||
# nano_project 本机一步步部署指南
|
||||
# Beaver Project 本机部署指南
|
||||
|
||||
这份文档适合第一次在本机把整个项目跑起来的人,目标是:
|
||||
|
||||
- 在一台 `Linux` 或 `WSL2 Ubuntu` 机器上
|
||||
- 用 `Docker` 跑完整链路
|
||||
- 最后能在浏览器里注册账号,并自动创建你的专属实例
|
||||
|
||||
这套项目当前的推荐本机测试方式是:
|
||||
这份文档用于在一台 Linux 或 WSL2 Ubuntu 机器上跑完整链路:
|
||||
|
||||
- `auth-portal`
|
||||
- `authz-service`
|
||||
- `deploy-control`
|
||||
- `router-proxy`
|
||||
- `app-instance`
|
||||
- 自动创建出来的 `app-instance`
|
||||
|
||||
全部一起跑。
|
||||
目标结果:
|
||||
|
||||
如果你只单独跑某个前端页面,页面能打开,但注册、登录、创建实例这些核心能力不一定会通。
|
||||
- 浏览器能打开 `http://127.0.0.1:3081/register`
|
||||
- 注册账号后自动创建专属实例
|
||||
- 浏览器跳转到 `http://<slug>.127.0.0.1.nip.io:8088`
|
||||
|
||||
---
|
||||
如果你只单独启动某个前端页面,页面可以打开,但注册、登录、创建实例这些动作不一定能通。
|
||||
|
||||
## 0. 先说前提
|
||||
## 0. 前提
|
||||
|
||||
### 适合的环境
|
||||
|
||||
推荐:
|
||||
推荐环境:
|
||||
|
||||
- Linux
|
||||
- WSL2 Ubuntu
|
||||
|
||||
不推荐直接按这份文档在纯 Windows 命令行里照抄,因为这里依赖:
|
||||
|
||||
- Docker
|
||||
- Bash 脚本
|
||||
- Docker Socket 挂载
|
||||
- 宿主机目录挂载
|
||||
|
||||
### 你需要先装好的工具
|
||||
需要工具:
|
||||
|
||||
- `docker`
|
||||
- `git`
|
||||
@ -44,7 +31,7 @@
|
||||
- `openssl`
|
||||
- `python3`
|
||||
|
||||
先检查:
|
||||
检查:
|
||||
|
||||
```bash
|
||||
docker --version
|
||||
@ -54,143 +41,89 @@ openssl version
|
||||
curl --version
|
||||
```
|
||||
|
||||
如果 `docker ps` 报错,先把 Docker 启动起来。
|
||||
|
||||
---
|
||||
如果 `docker ps` 报错,先启动 Docker。
|
||||
|
||||
## 1. 进入项目根目录
|
||||
|
||||
```bash
|
||||
cd /home/ivan/xuan/nano_project
|
||||
```
|
||||
|
||||
你执行完以后,建议顺手确认一下当前目录:
|
||||
|
||||
```bash
|
||||
cd /home/ivan/xuan/beaver_project
|
||||
pwd
|
||||
```
|
||||
|
||||
你应该看到:
|
||||
预期目录:
|
||||
|
||||
```text
|
||||
/home/ivan/xuan/nano_project
|
||||
/home/ivan/xuan/beaver_project
|
||||
```
|
||||
|
||||
---
|
||||
## 2. 准备本机测试变量
|
||||
|
||||
## 2. 准备一套本机测试变量
|
||||
本机测试推荐用 `127.0.0.1.nip.io`。例如:
|
||||
|
||||
### 为什么这里用 `127.0.0.1.nip.io`
|
||||
```text
|
||||
alice.127.0.0.1.nip.io -> 127.0.0.1
|
||||
```
|
||||
|
||||
因为这是最省事的本机测试域名方案。
|
||||
这样 `router-proxy` 可以按子域名区分不同实例。
|
||||
|
||||
它的作用是:
|
||||
|
||||
- `alice.127.0.0.1.nip.io`
|
||||
- 自动解析到 `127.0.0.1`
|
||||
|
||||
这样 `router-proxy` 就能按子域名区分不同实例。
|
||||
|
||||
### 直接复制执行
|
||||
直接执行:
|
||||
|
||||
```bash
|
||||
export PROJECT_ROOT=/home/ivan/xuan/nano_project
|
||||
export NANO_NET=nano-instance-edge
|
||||
export PROJECT_ROOT=/home/ivan/xuan/beaver_project
|
||||
export BEAVER_NET=beaver-instance-edge
|
||||
|
||||
export NANO_DEPLOY_TOKEN="$(openssl rand -hex 32)"
|
||||
export NANO_AUTHZ_INTERNAL_TOKEN="$(openssl rand -hex 32)"
|
||||
export BEAVER_DEPLOY_TOKEN="$(openssl rand -hex 32)"
|
||||
export BEAVER_AUTHZ_INTERNAL_TOKEN="$(openssl rand -hex 32)"
|
||||
|
||||
export NANO_SERVER_IP=127.0.0.1
|
||||
export NANO_BASE_DOMAIN=127.0.0.1.nip.io
|
||||
export BEAVER_BASE_DOMAIN=127.0.0.1.nip.io
|
||||
|
||||
export NANO_PROVIDER=openai
|
||||
export NANO_MODEL=openai/gpt-5
|
||||
export NANO_API_KEY='把这里换成你自己的模型 API Key'
|
||||
export NANO_API_BASE=''
|
||||
export BEAVER_AUTHZ_URL='http://beaver-authz-service:19090'
|
||||
export BEAVER_DEPLOY_URL='http://beaver-deploy-control:8090'
|
||||
|
||||
export NANO_AUTHZ_URL='http://nano-authz-service:19090'
|
||||
export NANO_OUTLOOK_MCP_URL=''
|
||||
export NANO_OUTLOOK_MCP_SERVER_ID='outlook_mcp'
|
||||
export NANO_DEPLOY_URL='http://nano-deploy-control:8090'
|
||||
export BEAVER_OUTLOOK_MCP_URL=''
|
||||
export BEAVER_OUTLOOK_MCP_SERVER_ID='outlook_mcp'
|
||||
```
|
||||
|
||||
### 这里每个变量大概是干什么的
|
||||
变量说明:
|
||||
|
||||
- `PROJECT_ROOT`
|
||||
- 仓库根目录
|
||||
- `NANO_NET`
|
||||
- 所有容器共用的 Docker 网络
|
||||
- `NANO_DEPLOY_TOKEN`
|
||||
- `auth-portal` / `authz-service` 调 `deploy-control` 时的鉴权 token
|
||||
- `NANO_AUTHZ_INTERNAL_TOKEN`
|
||||
- AuthZ 内部接口 token
|
||||
- `NANO_BASE_DOMAIN`
|
||||
- 实例基础域名
|
||||
- `NANO_PROVIDER`
|
||||
- 新实例默认模型提供商
|
||||
- `NANO_MODEL`
|
||||
- 新实例默认模型
|
||||
- `NANO_API_KEY`
|
||||
- 新实例默认模型 API Key
|
||||
- `NANO_API_BASE`
|
||||
- 自定义模型网关地址,没有就留空
|
||||
- `NANO_AUTHZ_URL`
|
||||
- 容器网络内访问 AuthZ 的地址
|
||||
- `NANO_DEPLOY_URL`
|
||||
- 容器网络内访问 deploy-control 的地址
|
||||
- `NANO_OUTLOOK_MCP_URL`
|
||||
- 可选;如果你有独立 Outlook MCP 服务,可以在这里填
|
||||
- `NANO_OUTLOOK_MCP_SERVER_ID`
|
||||
- Outlook MCP 默认 server id,当前推荐固定 `outlook_mcp`
|
||||
| 变量 | 作用 |
|
||||
| --- | --- |
|
||||
| `PROJECT_ROOT` | 仓库根目录 |
|
||||
| `BEAVER_NET` | 所有容器共用的 Docker network |
|
||||
| `BEAVER_DEPLOY_TOKEN` | `auth-portal` / `authz-service` 调 `deploy-control` 的 token |
|
||||
| `BEAVER_AUTHZ_INTERNAL_TOKEN` | AuthZ 内部接口 token |
|
||||
| `BEAVER_BASE_DOMAIN` | 新实例的基域名 |
|
||||
| `BEAVER_AUTHZ_URL` | 容器网络内访问 AuthZ 的地址 |
|
||||
| `BEAVER_DEPLOY_URL` | 容器网络内访问 deploy-control 的地址 |
|
||||
| `BEAVER_OUTLOOK_MCP_URL` | 可选 Outlook MCP HTTP 地址 |
|
||||
| `BEAVER_OUTLOOK_MCP_SERVER_ID` | Outlook MCP server id,默认 `outlook_mcp` |
|
||||
|
||||
### 一个特别重要的提醒
|
||||
|
||||
`NANO_API_KEY` 不能空着。
|
||||
|
||||
如果这里不填,新用户注册时虽然页面可能能走到一半,但自动创建 `app-instance` 时大概率失败,因为实例配置里需要 `APP_INSTANCE_API_KEY`。
|
||||
|
||||
`NANO_AUTHZ_URL` 和 `NANO_DEPLOY_URL` 也不能留空,而且必须带协议头。
|
||||
|
||||
正确写法:
|
||||
`BEAVER_AUTHZ_URL` 和 `BEAVER_DEPLOY_URL` 必须带协议头。正确写法:
|
||||
|
||||
```text
|
||||
http://nano-authz-service:19090
|
||||
http://nano-deploy-control:8090
|
||||
http://beaver-authz-service:19090
|
||||
http://beaver-deploy-control:8090
|
||||
```
|
||||
|
||||
错误写法:
|
||||
|
||||
```text
|
||||
nano-authz-service:19090
|
||||
nano-deploy-control:8090
|
||||
172.19.207.13:19090
|
||||
172.19.207.13:8090
|
||||
beaver-authz-service:19090
|
||||
beaver-deploy-control:8090
|
||||
127.0.0.1:19090
|
||||
127.0.0.1:8090
|
||||
```
|
||||
|
||||
如果这里漏了 `http://`,注册页很容易直接报:
|
||||
如果漏了 `http://`,注册页可能报:
|
||||
|
||||
```text
|
||||
502: Request URL is missing an 'http://' or 'https://' protocol.
|
||||
```
|
||||
|
||||
还有一个很容易忽略的点:
|
||||
如果你改了 shell 里的变量,已经运行的容器不会自动更新。改完这些变量后,至少要重建:
|
||||
|
||||
- 你在 shell 里重新 `export NANO_DEPLOY_URL=...`
|
||||
- 不会自动修改已经在运行中的 `nano-authz-service` 和 `nano-auth-portal`
|
||||
|
||||
也就是说:
|
||||
|
||||
- 变量改对了
|
||||
- 但容器没重建
|
||||
|
||||
注册页还是会继续报同一个 502。
|
||||
|
||||
改完变量以后,至少要重建这些容器:
|
||||
|
||||
- `nano-authz-service`
|
||||
- `nano-auth-portal`
|
||||
|
||||
---
|
||||
- `beaver-authz-service`
|
||||
- `beaver-auth-portal`
|
||||
|
||||
## 3. 创建运行目录
|
||||
|
||||
@ -202,257 +135,169 @@ mkdir -p \
|
||||
"$PROJECT_ROOT/router-proxy/runtime/conf.d"
|
||||
```
|
||||
|
||||
这一步的作用是给下面几个东西留持久化空间:
|
||||
这些目录保存:
|
||||
|
||||
- AuthZ 数据
|
||||
- 实例注册表
|
||||
- 每个用户实例的配置目录
|
||||
- router-proxy 生成出来的路由文件
|
||||
|
||||
---
|
||||
- 每个用户实例的配置和数据
|
||||
- `router-proxy` 生成的路由文件
|
||||
|
||||
## 4. 构建镜像
|
||||
|
||||
第一次构建会比较久,正常情况要等几分钟。
|
||||
|
||||
```bash
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
docker build -t nano/app-instance:latest app-instance
|
||||
docker build -t nano/authz-service:latest authz-service
|
||||
docker build -t nano/deploy-control:latest deploy-control
|
||||
docker build -t nano/auth-portal:latest auth-portal/src
|
||||
docker build -t beaver/app-instance:latest app-instance
|
||||
docker build -t beaver/authz-service:latest authz-service
|
||||
docker build -t beaver/deploy-control:latest deploy-control
|
||||
docker build -t beaver/auth-portal:latest auth-portal/src
|
||||
```
|
||||
|
||||
如果中间有某个镜像失败,不要继续往下跑,先把失败那一步修掉。
|
||||
|
||||
常见失败原因:
|
||||
|
||||
- Docker 没启动
|
||||
- 网络拉镜像失败
|
||||
- 你的本机磁盘空间不够
|
||||
|
||||
---
|
||||
如果某个镜像构建失败,先修构建错误,不要继续往下跑。
|
||||
|
||||
## 5. 创建共享 Docker 网络
|
||||
|
||||
```bash
|
||||
docker network inspect "$NANO_NET" >/dev/null 2>&1 || docker network create "$NANO_NET"
|
||||
docker network inspect "$BEAVER_NET" >/dev/null 2>&1 || docker network create "$BEAVER_NET"
|
||||
docker network ls | grep "$BEAVER_NET"
|
||||
```
|
||||
|
||||
执行完后可确认:
|
||||
|
||||
```bash
|
||||
docker network ls | grep "$NANO_NET"
|
||||
```
|
||||
|
||||
应该能看到:
|
||||
预期能看到:
|
||||
|
||||
```text
|
||||
nano-instance-edge
|
||||
beaver-instance-edge
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 启动统一入口代理 `router-proxy`
|
||||
## 6. 启动 router-proxy
|
||||
|
||||
```bash
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
PROXY_NETWORK_NAME="$NANO_NET" \
|
||||
PROXY_NETWORK_NAME="$BEAVER_NET" \
|
||||
PROXY_HTTP_PORT=8088 \
|
||||
./router-proxy/start-proxy.sh --replace
|
||||
```
|
||||
|
||||
启动后,统一入口走:
|
||||
实例统一入口:
|
||||
|
||||
```text
|
||||
http://<你的实例slug>.127.0.0.1.nip.io:8088
|
||||
http://<slug>.127.0.0.1.nip.io:8088
|
||||
```
|
||||
|
||||
例如:
|
||||
示例:
|
||||
|
||||
```text
|
||||
http://alice.127.0.0.1.nip.io:8088
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 启动 `authz-service`
|
||||
## 7. 启动 authz-service
|
||||
|
||||
```bash
|
||||
docker rm -f nano-authz-service >/dev/null 2>&1 || true
|
||||
docker rm -f beaver-authz-service >/dev/null 2>&1 || true
|
||||
|
||||
docker run -d \
|
||||
--name nano-authz-service \
|
||||
--name beaver-authz-service \
|
||||
--restart unless-stopped \
|
||||
--network "$NANO_NET" \
|
||||
--network "$BEAVER_NET" \
|
||||
-p 19090:19090 \
|
||||
-v "$PROJECT_ROOT/authz-service/runtime/data:/var/lib/authz-service/data" \
|
||||
-e AUTHZ_ISSUER="$NANO_AUTHZ_URL" \
|
||||
-e AUTHZ_INTERNAL_TOKEN="$NANO_AUTHZ_INTERNAL_TOKEN" \
|
||||
-e DEPLOY_API_BASE_URL="$NANO_DEPLOY_URL" \
|
||||
-e DEPLOY_API_TOKEN="$NANO_DEPLOY_TOKEN" \
|
||||
nano/authz-service:latest
|
||||
-e AUTHZ_ISSUER="$BEAVER_AUTHZ_URL" \
|
||||
-e AUTHZ_INTERNAL_TOKEN="$BEAVER_AUTHZ_INTERNAL_TOKEN" \
|
||||
-e DEPLOY_API_BASE_URL="$BEAVER_DEPLOY_URL" \
|
||||
-e DEPLOY_API_TOKEN="$BEAVER_DEPLOY_TOKEN" \
|
||||
beaver/authz-service:latest
|
||||
```
|
||||
|
||||
### 这里有个很关键的坑
|
||||
重点:
|
||||
|
||||
`AUTHZ_ISSUER` 这里不能写成:
|
||||
- `AUTHZ_ISSUER` 在当前部署里要写 `http://beaver-authz-service:19090`
|
||||
- 不要写 `http://127.0.0.1:19090`
|
||||
- 新创建的 `app-instance` 容器要通过 Docker network 访问 AuthZ
|
||||
|
||||
```text
|
||||
http://127.0.0.1:19090
|
||||
```
|
||||
|
||||
因为后面新创建的 `app-instance` 也是通过 Docker 网络去访问 AuthZ 的。
|
||||
|
||||
所以这里要写容器网络里可访问的地址:
|
||||
|
||||
```text
|
||||
http://nano-authz-service:19090
|
||||
```
|
||||
|
||||
`DEPLOY_API_BASE_URL` 也一样,不能空,不能只写 `host:port`。
|
||||
|
||||
这里如果传成空字符串,或者写成:
|
||||
|
||||
```text
|
||||
nano-deploy-control:8090
|
||||
```
|
||||
|
||||
注册页会在 `authz-service -> deploy-control` 这一步直接报:
|
||||
|
||||
```text
|
||||
502: Request URL is missing an 'http://' or 'https://' protocol.
|
||||
```
|
||||
|
||||
启动完可以立刻确认:
|
||||
检查关键环境变量:
|
||||
|
||||
```bash
|
||||
docker inspect nano-authz-service --format '{{range .Config.Env}}{{println .}}{{end}}' | egrep '^(AUTHZ_ISSUER|DEPLOY_API_BASE_URL)='
|
||||
docker inspect beaver-authz-service --format '{{range .Config.Env}}{{println .}}{{end}}' \
|
||||
| egrep '^(AUTHZ_ISSUER|DEPLOY_API_BASE_URL)='
|
||||
```
|
||||
|
||||
---
|
||||
## 8. 启动 deploy-control
|
||||
|
||||
## 8. 启动 `deploy-control`
|
||||
`deploy-control` 会挂载 Docker socket,再创建新的 `app-instance` 容器。这里最容易错的是路径挂载:
|
||||
|
||||
这一步最容易配错的点是挂载目录。
|
||||
|
||||
一定要注意:
|
||||
|
||||
- `app-instance` 和 `router-proxy` 的宿主机路径,要按原路径挂进容器
|
||||
- 不能偷懒挂到容器里的另一个短路径比如 `/app-instance`
|
||||
- 同时要把 `APP_INSTANCE_DIR` 和 `ROUTER_PROXY_DIR` 也明确传进去
|
||||
- 要把宿主机真实路径按原路径挂进容器。
|
||||
- 不要把 `app-instance` 挂到容器里的 `/app-instance` 这种短路径。
|
||||
- `APP_INSTANCE_DIR` 和 `ROUTER_PROXY_DIR` 要和挂载路径一致。
|
||||
|
||||
直接执行:
|
||||
|
||||
```bash
|
||||
docker rm -f nano-deploy-control >/dev/null 2>&1 || true
|
||||
docker rm -f beaver-deploy-control >/dev/null 2>&1 || true
|
||||
|
||||
docker run -d \
|
||||
--name nano-deploy-control \
|
||||
--name beaver-deploy-control \
|
||||
--restart unless-stopped \
|
||||
--network "$NANO_NET" \
|
||||
--network "$BEAVER_NET" \
|
||||
-p 8090:8090 \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v "$PROJECT_ROOT/app-instance:$PROJECT_ROOT/app-instance" \
|
||||
-v "$PROJECT_ROOT/router-proxy:$PROJECT_ROOT/router-proxy" \
|
||||
-e APP_INSTANCE_DIR="$PROJECT_ROOT/app-instance" \
|
||||
-e ROUTER_PROXY_DIR="$PROJECT_ROOT/router-proxy" \
|
||||
-e DEPLOY_CONTROL_API_TOKEN="$NANO_DEPLOY_TOKEN" \
|
||||
-e APP_INSTANCE_IMAGE="nano/app-instance:latest" \
|
||||
-e APP_INSTANCE_NETWORK_NAME="$NANO_NET" \
|
||||
-e APP_INSTANCE_PROVIDER="$NANO_PROVIDER" \
|
||||
-e APP_INSTANCE_MODEL="$NANO_MODEL" \
|
||||
-e APP_INSTANCE_API_KEY="$NANO_API_KEY" \
|
||||
-e APP_INSTANCE_API_BASE="$NANO_API_BASE" \
|
||||
-e DEFAULT_AUTHZ_BASE_URL="$NANO_AUTHZ_URL" \
|
||||
-e DEFAULT_AUTHZ_OUTLOOK_MCP_URL="$NANO_OUTLOOK_MCP_URL" \
|
||||
-e DEFAULT_OUTLOOK_MCP_SERVER_ID="$NANO_OUTLOOK_MCP_SERVER_ID" \
|
||||
-e DEPLOY_CONTROL_API_TOKEN="$BEAVER_DEPLOY_TOKEN" \
|
||||
-e APP_INSTANCE_IMAGE="beaver/app-instance:latest" \
|
||||
-e APP_INSTANCE_NETWORK_NAME="$BEAVER_NET" \
|
||||
-e DEFAULT_AUTHZ_BASE_URL="$BEAVER_AUTHZ_URL" \
|
||||
-e DEFAULT_AUTHZ_OUTLOOK_MCP_URL="$BEAVER_OUTLOOK_MCP_URL" \
|
||||
-e DEFAULT_OUTLOOK_MCP_SERVER_ID="$BEAVER_OUTLOOK_MCP_SERVER_ID" \
|
||||
-e DEPLOY_PUBLIC_SCHEME="http" \
|
||||
-e DEPLOY_PUBLIC_BASE_DOMAIN="$NANO_BASE_DOMAIN" \
|
||||
-e DEPLOY_PUBLIC_BASE_DOMAIN="$BEAVER_BASE_DOMAIN" \
|
||||
-e DEPLOY_PUBLIC_PORT="8088" \
|
||||
-e DEPLOY_AUTO_START_PROXY="1" \
|
||||
nano/deploy-control:latest
|
||||
beaver/deploy-control:latest
|
||||
```
|
||||
|
||||
### 这一步在做什么
|
||||
当前版本创建实例时会传 `--skip-provider-config`,也就是先不写 provider、model 或 API key。注册成功后,`auth-portal` 会进入模型配置引导页,再调用 `deploy-control /api/instances/configure-provider` 写入该实例的 `config.json` 并重启容器。
|
||||
|
||||
`deploy-control` 会负责:
|
||||
|
||||
- 收到“创建实例”的请求
|
||||
- 调用 `app-instance/create-instance.sh`
|
||||
- 通过 Docker 创建对应用户实例
|
||||
- 刷新 `router-proxy`
|
||||
|
||||
---
|
||||
|
||||
## 9. 启动 `auth-portal`
|
||||
## 9. 启动 auth-portal
|
||||
|
||||
```bash
|
||||
docker rm -f nano-auth-portal >/dev/null 2>&1 || true
|
||||
docker rm -f beaver-auth-portal >/dev/null 2>&1 || true
|
||||
|
||||
docker run -d \
|
||||
--name nano-auth-portal \
|
||||
--name beaver-auth-portal \
|
||||
--restart unless-stopped \
|
||||
--network "$NANO_NET" \
|
||||
--network "$BEAVER_NET" \
|
||||
-p 3081:3081 \
|
||||
-e AUTHZ_API_BASE_URL="$NANO_AUTHZ_URL" \
|
||||
-e DEPLOY_API_BASE_URL="$NANO_DEPLOY_URL" \
|
||||
-e DEPLOY_API_TOKEN="$NANO_DEPLOY_TOKEN" \
|
||||
nano/auth-portal:latest
|
||||
-e AUTHZ_API_BASE_URL="$BEAVER_AUTHZ_URL" \
|
||||
-e DEPLOY_API_BASE_URL="$BEAVER_DEPLOY_URL" \
|
||||
-e DEPLOY_API_TOKEN="$BEAVER_DEPLOY_TOKEN" \
|
||||
beaver/auth-portal:latest
|
||||
```
|
||||
|
||||
这个页面就是用户看到的登录/注册入口。
|
||||
|
||||
虽然注册入口主要依赖 `AUTHZ_API_BASE_URL`,这里还是建议把 `DEPLOY_API_BASE_URL` 一起带上并确认非空,避免后面运行态调用 deploy-control 时再踩同一个坑。
|
||||
|
||||
启动完可以确认:
|
||||
检查关键环境变量:
|
||||
|
||||
```bash
|
||||
docker inspect nano-auth-portal --format '{{range .Config.Env}}{{println .}}{{end}}' | egrep '^(AUTHZ_API_BASE_URL|DEPLOY_API_BASE_URL)='
|
||||
docker inspect beaver-auth-portal --format '{{range .Config.Env}}{{println .}}{{end}}' \
|
||||
| egrep '^(AUTHZ_API_BASE_URL|DEPLOY_API_BASE_URL)='
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 做健康检查
|
||||
|
||||
### 先检查接口
|
||||
## 10. 健康检查
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:19090/healthz
|
||||
curl http://127.0.0.1:8090/healthz
|
||||
curl -I http://127.0.0.1:3081
|
||||
```
|
||||
|
||||
你应该大致看到:
|
||||
|
||||
- `authz-service` 返回健康 JSON
|
||||
- `deploy-control` 返回健康 JSON
|
||||
- `auth-portal` 返回 `HTTP/1.1 200 OK`
|
||||
|
||||
### 再看容器状态
|
||||
|
||||
```bash
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
||||
docker logs --tail=50 beaver-router-proxy
|
||||
```
|
||||
|
||||
你至少应该能看到这些容器:
|
||||
至少应该看到这些容器:
|
||||
|
||||
- `nano-authz-service`
|
||||
- `nano-deploy-control`
|
||||
- `nano-auth-portal`
|
||||
- `nano-router-proxy`
|
||||
|
||||
### 再看一下代理日志
|
||||
|
||||
```bash
|
||||
docker logs --tail=50 nano-router-proxy
|
||||
```
|
||||
|
||||
如果这一步没有明显报错,就可以开始浏览器测试了。
|
||||
|
||||
---
|
||||
- `beaver-authz-service`
|
||||
- `beaver-deploy-control`
|
||||
- `beaver-auth-portal`
|
||||
- `beaver-router-proxy`
|
||||
|
||||
## 11. 浏览器首次测试
|
||||
|
||||
@ -462,316 +307,177 @@ docker logs --tail=50 nano-router-proxy
|
||||
http://127.0.0.1:3081/register
|
||||
```
|
||||
|
||||
然后按顺序操作:
|
||||
预期流程:
|
||||
|
||||
1. 注册一个新账号
|
||||
2. 注册成功后,系统会自动创建一个你的专属实例
|
||||
3. 浏览器应该跳到你的实例地址
|
||||
1. 注册一个新账号。
|
||||
2. Portal 创建不含模型凭证的实例。
|
||||
3. 页面进入模型配置引导。
|
||||
4. 填 provider、model、API key 后确认,或暂时跳过。
|
||||
5. 浏览器跳到你的实例地址。
|
||||
|
||||
跳转目标一般长这样:
|
||||
|
||||
```text
|
||||
http://你的slug.127.0.0.1.nip.io:8088
|
||||
```
|
||||
|
||||
例如:
|
||||
跳转目标示例:
|
||||
|
||||
```text
|
||||
http://alice.127.0.0.1.nip.io:8088
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. 确认实例真的被创建出来了
|
||||
## 12. 确认实例已创建
|
||||
|
||||
```bash
|
||||
cd "$PROJECT_ROOT/app-instance"
|
||||
./list-instances.sh
|
||||
./list-instances.sh --json
|
||||
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}' | grep app-instance
|
||||
```
|
||||
|
||||
你应该能看到类似:
|
||||
注册表里应包含:
|
||||
|
||||
- `instance_id`
|
||||
- `instance_slug`
|
||||
- `container_name`
|
||||
- `public_url`
|
||||
- `instance_host`
|
||||
|
||||
以及对应的 `app-instance-<slug>` 容器。
|
||||
## 13. 只看 auth-portal 页面
|
||||
|
||||
你还可以继续查:
|
||||
如果只想看 Portal 页面,不跑全链路:
|
||||
|
||||
```bash
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}' | grep app-instance
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. 如果你只是想单独看前端页面
|
||||
|
||||
如果你只是想看 `auth-portal` 页面样子,不跑全链路,也可以单独启动它的前端开发模式:
|
||||
|
||||
```bash
|
||||
cd /home/ivan/xuan/nano_project/auth-portal/src
|
||||
cd /home/ivan/xuan/beaver_project/auth-portal/src
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
然后打开:
|
||||
打开:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:3081
|
||||
```
|
||||
|
||||
但是要注意:
|
||||
注意:这只能看页面。注册、登录、创建实例仍依赖 `authz-service` 和 `deploy-control`。
|
||||
|
||||
- 这只能看页面
|
||||
- 注册、登录、创建实例这些动作是否成功,仍然取决于 `authz-service` 和 `deploy-control` 有没有另外启动
|
||||
|
||||
---
|
||||
|
||||
## 14. 一键排错命令
|
||||
|
||||
如果你感觉“不对劲”,先跑这几条:
|
||||
## 14. 常用排错命令
|
||||
|
||||
```bash
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
||||
|
||||
docker logs --tail=100 nano-authz-service
|
||||
docker logs --tail=100 nano-deploy-control
|
||||
docker logs --tail=100 nano-auth-portal
|
||||
docker logs --tail=100 nano-router-proxy
|
||||
docker logs --tail=100 beaver-authz-service
|
||||
docker logs --tail=100 beaver-deploy-control
|
||||
docker logs --tail=100 beaver-auth-portal
|
||||
docker logs --tail=100 beaver-router-proxy
|
||||
|
||||
curl http://127.0.0.1:19090/healthz
|
||||
curl http://127.0.0.1:8090/healthz
|
||||
curl -I http://127.0.0.1:3081
|
||||
```
|
||||
|
||||
如果是实例创建失败,再加两条:
|
||||
实例创建失败时再看:
|
||||
|
||||
```bash
|
||||
cd "$PROJECT_ROOT/app-instance"
|
||||
./list-instances.sh --json
|
||||
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}' | grep app-instance
|
||||
```
|
||||
|
||||
如果注册页弹出:
|
||||
排查 URL 变量:
|
||||
|
||||
```bash
|
||||
docker inspect beaver-authz-service --format '{{range .Config.Env}}{{println .}}{{end}}' \
|
||||
| egrep '^(AUTHZ_ISSUER|DEPLOY_API_BASE_URL)='
|
||||
|
||||
docker inspect beaver-auth-portal --format '{{range .Config.Env}}{{println .}}{{end}}' \
|
||||
| egrep '^(AUTHZ_API_BASE_URL|DEPLOY_API_BASE_URL)='
|
||||
```
|
||||
|
||||
它们都必须是完整 URL,不能是空字符串,也不能是裸 `host:port`。
|
||||
|
||||
## 15. 常见问题
|
||||
|
||||
### 注册页报 URL 缺少协议
|
||||
|
||||
现象:
|
||||
|
||||
```text
|
||||
502: Request URL is missing an 'http://' or 'https://' protocol.
|
||||
```
|
||||
|
||||
优先查这两条:
|
||||
优先检查:
|
||||
|
||||
```bash
|
||||
docker inspect nano-authz-service --format '{{range .Config.Env}}{{println .}}{{end}}' | egrep '^(AUTHZ_ISSUER|DEPLOY_API_BASE_URL)='
|
||||
docker inspect nano-auth-portal --format '{{range .Config.Env}}{{println .}}{{end}}' | egrep '^(AUTHZ_API_BASE_URL|DEPLOY_API_BASE_URL)='
|
||||
```
|
||||
- `beaver-authz-service` 里的 `DEPLOY_API_BASE_URL`
|
||||
- `beaver-auth-portal` 里的 `AUTHZ_API_BASE_URL`
|
||||
- `beaver-auth-portal` 里的 `DEPLOY_API_BASE_URL`
|
||||
|
||||
重点看:
|
||||
如果你只是改了当前 shell 变量,但没有重建容器,旧值还会继续生效。
|
||||
|
||||
- `nano-authz-service` 里的 `DEPLOY_API_BASE_URL`
|
||||
- `nano-auth-portal` 里的 `AUTHZ_API_BASE_URL`
|
||||
### `AUTHZ_ISSUER` 写成了 `127.0.0.1`
|
||||
|
||||
它们都必须是完整 URL,不能是空字符串,也不能是裸 `host:port`。
|
||||
|
||||
如果你已经改过 `export NANO_DEPLOY_URL=...`,但这里查出来还是空,说明你只是改了当前 shell 变量,没有把容器重建掉。
|
||||
|
||||
这时直接按下面重建:
|
||||
|
||||
```bash
|
||||
export NANO_AUTHZ_URL='http://nano-authz-service:19090'
|
||||
export NANO_DEPLOY_URL='http://nano-deploy-control:8090'
|
||||
|
||||
export NANO_DEPLOY_TOKEN="$(docker inspect nano-deploy-control --format '{{range .Config.Env}}{{println .}}{{end}}' | sed -n 's/^DEPLOY_CONTROL_API_TOKEN=//p')"
|
||||
export NANO_AUTHZ_INTERNAL_TOKEN="$(docker inspect nano-authz-service --format '{{range .Config.Env}}{{println .}}{{end}}' | sed -n 's/^AUTHZ_INTERNAL_TOKEN=//p')"
|
||||
|
||||
docker rm -f nano-authz-service >/dev/null 2>&1 || true
|
||||
docker run -d \
|
||||
--name nano-authz-service \
|
||||
--restart unless-stopped \
|
||||
--network "$NANO_NET" \
|
||||
-p 19090:19090 \
|
||||
-v "$PROJECT_ROOT/authz-service/runtime/data:/var/lib/authz-service/data" \
|
||||
-e AUTHZ_ISSUER="$NANO_AUTHZ_URL" \
|
||||
-e AUTHZ_INTERNAL_TOKEN="$NANO_AUTHZ_INTERNAL_TOKEN" \
|
||||
-e DEPLOY_API_BASE_URL="$NANO_DEPLOY_URL" \
|
||||
-e DEPLOY_API_TOKEN="$NANO_DEPLOY_TOKEN" \
|
||||
nano/authz-service:latest
|
||||
|
||||
docker rm -f nano-auth-portal >/dev/null 2>&1 || true
|
||||
docker run -d \
|
||||
--name nano-auth-portal \
|
||||
--restart unless-stopped \
|
||||
--network "$NANO_NET" \
|
||||
-p 3081:3081 \
|
||||
-e AUTHZ_API_BASE_URL="$NANO_AUTHZ_URL" \
|
||||
-e DEPLOY_API_BASE_URL="$NANO_DEPLOY_URL" \
|
||||
-e DEPLOY_API_TOKEN="$NANO_DEPLOY_TOKEN" \
|
||||
nano/auth-portal:latest
|
||||
```
|
||||
|
||||
重建后再确认:
|
||||
|
||||
```bash
|
||||
docker inspect nano-authz-service --format '{{range .Config.Env}}{{println .}}{{end}}' | egrep '^(AUTHZ_ISSUER|DEPLOY_API_BASE_URL)='
|
||||
docker inspect nano-auth-portal --format '{{range .Config.Env}}{{println .}}{{end}}' | egrep '^(AUTHZ_API_BASE_URL|DEPLOY_API_BASE_URL)='
|
||||
```
|
||||
|
||||
你必须看到:
|
||||
|
||||
```text
|
||||
DEPLOY_API_BASE_URL=http://nano-deploy-control:8090
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 15. 最常见的坑
|
||||
|
||||
### 1. API Key 没填
|
||||
|
||||
现象:
|
||||
|
||||
- 注册页面提交后创建实例失败
|
||||
|
||||
原因:
|
||||
|
||||
- `APP_INSTANCE_API_KEY` 没有有效值
|
||||
|
||||
### 2. Docker 没启动
|
||||
|
||||
现象:
|
||||
|
||||
- `deploy-control` 无法创建实例
|
||||
- 或 `docker ps` 本身就报错
|
||||
|
||||
### 3. `AUTHZ_ISSUER` 写成了 `127.0.0.1`
|
||||
|
||||
错误写法:
|
||||
错误:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:19090
|
||||
```
|
||||
|
||||
正确写法:
|
||||
正确:
|
||||
|
||||
```text
|
||||
http://nano-authz-service:19090
|
||||
http://beaver-authz-service:19090
|
||||
```
|
||||
|
||||
原因:
|
||||
原因是 `app-instance` 容器里的 `127.0.0.1` 指向它自己。
|
||||
|
||||
- 新实例容器里访问不到宿主机自己的 `127.0.0.1:19090`
|
||||
|
||||
### 4. `deploy-control` 的路径挂载写错
|
||||
### deploy-control 路径挂载写错
|
||||
|
||||
错误思路:
|
||||
|
||||
- 把宿主机的 `app-instance` 挂到容器里的 `/app-instance`
|
||||
```text
|
||||
宿主机 app-instance -> 容器 /app-instance
|
||||
```
|
||||
|
||||
正确思路:
|
||||
|
||||
- 宿主机原路径挂进去
|
||||
- 并设置:
|
||||
- `APP_INSTANCE_DIR="$PROJECT_ROOT/app-instance"`
|
||||
- `ROUTER_PROXY_DIR="$PROJECT_ROOT/router-proxy"`
|
||||
|
||||
### 5. `NANO_DEPLOY_URL` 或 `NANO_AUTHZ_URL` 没带 `http://`
|
||||
|
||||
典型现象:
|
||||
|
||||
- 注册页直接弹:
|
||||
- `502: Request URL is missing an 'http://' or 'https://' protocol.`
|
||||
|
||||
原因:
|
||||
|
||||
- `authz-service` 用 `DEPLOY_API_BASE_URL` 去调 `deploy-control`
|
||||
- `auth-portal` 用 `AUTHZ_API_BASE_URL` 去调 `authz-service`
|
||||
- 这些值如果是空,或者写成 `nano-deploy-control:8090` 这种不带协议的字符串,请求会直接失败
|
||||
- 就算你后来在 shell 里改对了,如果没重建相关容器,老的错误值仍然会继续生效
|
||||
|
||||
正确写法:
|
||||
|
||||
```text
|
||||
http://nano-authz-service:19090
|
||||
http://nano-deploy-control:8090
|
||||
$PROJECT_ROOT/app-instance -> $PROJECT_ROOT/app-instance
|
||||
$PROJECT_ROOT/router-proxy -> $PROJECT_ROOT/router-proxy
|
||||
```
|
||||
|
||||
### 6. `nip.io` 解析失败
|
||||
因为 `deploy-control` 会通过宿主机 Docker socket 再创建新容器,传给 Docker 的 bind mount 源路径必须是宿主机真实路径。
|
||||
|
||||
如果实例跳转地址打不开,先试:
|
||||
### `nip.io` 解析失败
|
||||
|
||||
检查:
|
||||
|
||||
```bash
|
||||
ping 127.0.0.1.nip.io
|
||||
```
|
||||
|
||||
如果你本地网络把 `nip.io` 拦了,这套子域名测试方式就会失效。
|
||||
如果本地网络屏蔽了 `nip.io`,子域名测试会失败。可以临时换成本机 hosts 或正式域名。
|
||||
|
||||
### 7. 端口被占用
|
||||
### 端口被占用
|
||||
|
||||
默认会用到这些端口:
|
||||
默认端口:
|
||||
|
||||
- `3081`
|
||||
- `8088`
|
||||
- `8090`
|
||||
- `19090`
|
||||
- `8088`
|
||||
|
||||
你可以先查:
|
||||
检查:
|
||||
|
||||
```bash
|
||||
ss -ltnp | grep -E '3081|8090|19090|8088'
|
||||
ss -ltnp | grep -E '3081|8088|8090|19090'
|
||||
```
|
||||
|
||||
---
|
||||
## 16. 重新部署基础容器
|
||||
|
||||
## 16. 如果你要重新来一遍
|
||||
|
||||
如果你只是想“重新部署这四个基础容器”,可以先停掉它们:
|
||||
只重建基础四个容器:
|
||||
|
||||
```bash
|
||||
docker rm -f \
|
||||
nano-auth-portal \
|
||||
nano-authz-service \
|
||||
nano-deploy-control \
|
||||
nano-router-proxy 2>/dev/null || true
|
||||
beaver-auth-portal \
|
||||
beaver-authz-service \
|
||||
beaver-deploy-control \
|
||||
beaver-router-proxy 2>/dev/null || true
|
||||
```
|
||||
|
||||
如果你还想把旧实例容器也一起清掉,再额外处理 `app-instance-*`。
|
||||
|
||||
注意:
|
||||
|
||||
- 不要在你还需要旧数据的时候乱删 `runtime/`
|
||||
- `authz-service/runtime/data` 和 `app-instance/runtime/instances` 里都有持久化数据
|
||||
|
||||
---
|
||||
|
||||
## 17. 本机部署成功后的结果应该是什么
|
||||
|
||||
如果整个流程正常,最后你会得到:
|
||||
|
||||
- 一个可以打开的注册页:
|
||||
- `http://127.0.0.1:3081/register`
|
||||
- 一个统一实例入口代理:
|
||||
- `http://<slug>.127.0.0.1.nip.io:8088`
|
||||
- 一个能自动创建用户专属容器的部署控制面
|
||||
- 一份实例注册表:
|
||||
- `app-instance/runtime/registry/instances.json`
|
||||
|
||||
---
|
||||
|
||||
## 18. 你下一步最建议做什么
|
||||
|
||||
第一次建议这样测:
|
||||
|
||||
1. 用全新用户名注册一个测试账号
|
||||
2. 确认浏览器跳到了你的实例 URL
|
||||
3. 再执行 `./app-instance/list-instances.sh --json`
|
||||
4. 确认注册表里真的有这条实例记录
|
||||
|
||||
如果你后面想要,我还可以继续补两份文档:
|
||||
|
||||
- `服务器部署指南.md`
|
||||
- 面向公网服务器、固定 IP、长期运行
|
||||
- `常见报错排查.md`
|
||||
- 专门收集 502、超时、实例起不来、MCP 鉴权失败这类问题
|
||||
这不会自动删除实例数据。如果你还需要旧账号、旧实例或模型配置,不要删除 `runtime/` 目录。
|
||||
|
||||
Reference in New Issue
Block a user