# app-instance 单实例应用单元: - 一个 Docker 容器里同时运行前端、后端和 Nginx 反代 - 前端走 `/` - 后端 API 走 `/api` - WebSocket 走 `/ws` ## 关键文件 - `Dockerfile` - 统一镜像构建入口 - `entrypoint.sh` - 容器内启动前端、后端、Nginx - `create-instance.sh` - 创建实例目录、生成配置、启动容器、写注册表 - `remove-instance.sh` - 删除容器、移除注册表、可选清理实例目录 - `list-instances.sh` - 查看当前注册实例 - `instance-registry.py` - 维护 `runtime/registry/instances.json` ## 注册表 默认注册表路径: ```text runtime/registry/instances.json ``` 每条记录至少包含: - `instance_id` - `instance_slug` - `container_name` - `host_port` - `public_url` - `instance_root` - `image_name` ## 常用命令 ### 1. 构建镜像 ```bash docker build -t beaver/app-instance:latest . ``` ### 2. 创建实例 ```bash ./create-instance.sh \ --image beaver/app-instance:latest \ --instance-id demo-001 \ --auth-username admin \ --auth-password 123456 \ --api-key 'your-api-key' ``` 可选参数: - `--host-port` - `--public-url` - `--username` - `--email` - `--instance-host` - `--authz-base-url` - `--backend-id` - `--client-id` - `--client-secret` - `--network` - `--host-bind-ip` - `--initial-skills-dir` - `--skip-initial-skills` - `--build` - `--replace` ### 3. 查看实例 ```bash ./list-instances.sh ./list-instances.sh --json ``` ### 4. 删除实例 ```bash ./remove-instance.sh --instance-id demo-001 ``` 如果要把实例目录也一并清掉: ```bash ./remove-instance.sh --instance-id demo-001 --purge-data ``` ## 目录约定 默认实例数据目录: ```text runtime/instances// ``` 其中会生成: ```text runtime/instances// └── beaver-home ├── config.json ├── web_auth_users.json └── workspace/ ``` 这个目录是单用户 sandbox 的配置与数据边界。容器内会把它挂到: ```text /root/.beaver/ ``` 并设置: ```text BEAVER_CONFIG_PATH=/root/.beaver/config.json BEAVER_WORKSPACE=/root/.beaver/workspace ``` 所以模型 `provider/api_key/api_base/model` 配一次即可,Web / channel 请求不需要、也不应该携带 API Key。 `create-instance.sh` 默认会把仓库根目录的 `skills/` 非覆盖式复制到实例 workspace,并把同一个目录只读挂载到实例容器的 `/opt/app/initial-skills`。`entrypoint.sh` 每次启动都会用该目录补齐缺失的 published 初始 skills;已有 skill 目录不会被覆盖,index 只做并集追加。 ## 当前状态 这层已经支持: - 统一镜像构建 - 镜像内安装并启动新的 `beaver` 后端 - 实例创建 - 实例删除 - 实例列表 - 基于注册表的端口分配 - 为 deploy-control / router-proxy 记录用户名和实例 host ## 生产注意 - 实例容器的宿主机端口默认只绑定 `127.0.0.1` - 外部访问应统一走 `router-proxy` - 如果你确实要把单个实例端口直接暴露到公网,再显式传 `--host-bind-ip 0.0.0.0` - 使用共享 `external-connector` sidecar 时,每个实例容器都必须带自己的内部回调地址: `EXTERNAL_CONNECTOR_CALLBACK_BASE_URL=http://:8080` - 通过 `create-instance.sh --network ` 创建实例时,脚本会默认使用 `http://:8080` 作为回调地址;生产部署也可以用 `--external-connector-callback-base-url ` 显式覆盖 - `BEAVER_BRIDGE_BASE_URL` 只作为 sidecar 的旧连接或兜底地址;多实例部署不能依赖它路由所有入站事件 下一步可以继续接: - portal 调用创建实例 - URL 分配和反向代理 - 实例续期 / 停用 / 启用