沙箱与多用户 xunc / xunx¶
xunc 用 Docker 跑一次会话,xunx 用一个网关跑很多个用户的常驻容器。两者共用同一个镜像(默认 xun),
镜像构建见 安装。
xunc:容器会话¶
xunc 本身不运行智能体,它只做三件事:准备 /workspace、转发环境变量、在容器里启动 xuns(或你指定的命令)。
xunc # 容器内临时工作区,启动 Web 服务
xunc . # 把当前目录绑定挂载为 /workspace
xunc --copy . # 改为复制进 /workspace(之后不同步回宿主)
xunc --exec "xun" # 容器里跑终端入口
xunc --exec "" # 空字符串,退回镜像的默认 CMD
xunc --env "FOO=1,PATH" # 直接赋值 + 按名字转发
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
mount |
位置参数 | 无 | 要挂载 / 复制到 /workspace 的目录 |
--copy |
开关 | 关 | 复制而不是绑定挂载 |
--image |
str | xun |
使用的镜像 |
--env |
str,可重复 | [] |
逗号分隔:NAME=VALUE 直接赋值,其余按通配符从宿主转发 |
--name |
str | xun-<uuid8> |
容器名 |
--network |
bridge / host |
bridge |
网络模式 |
--port |
str,可重复 | ["18960"] |
bridge 模式下发布的端口,可逗号分隔多个 |
--exec |
str | xuns |
容器内执行的命令;空串退回镜像默认 CMD |
挂载与复制¶
- 不带
mount:容器自己的工作目录(/home/app)作为工作区,宿主机看不到。 - 绑定挂载(默认):容器内改动直接落到宿主目录;
--userns=host保证属主一致。 --copy:用docker cp复制进去,容器独占,宿主原目录不受影响。- 无论哪种方式,宿主
$XUN_HOME下的config.json、extensions/、skills/会被复制进容器的/.xun;x/(xunx的用户库)与conversation/(会话存档)会被跳过。
环境变量转发¶
容器内固定 ENV XUN_HOME=/.xun,因此宿主环境的转发规则是:
- 始终转发
XUN_*与_XUN_*;XUN_HOME明确排除。 --env里NAME=VALUE直接赋值;不含=的项按通配符匹配宿主变量转发;裸名字NAME即精确转发。--env可重复,值累积。
例如把宿主的代理与自定义模型端点带进容器:
export XUN_OPENAI_BASE_URL=https://gateway.internal/v1
xunc . --env "HTTP_PROXY,NO_PROXY,XUN_OPENAI_*"
端口与时区¶
bridge 模式只为 --port 指定的端口加 -p <port>:<port>;host 网络则全部直通。
容器时区跟随宿主的 /etc/localtime。
xunx:多用户网关¶
xunx 为每个用户维护一个常驻容器,用一个网关端口对外提供访问;容器内部端口固定从 18960 起。
xunx user-add alice
xunx serve --host 0.0.0.0 --port 18960
xunx shell alice --cwd /workspace
xunx pause alice
xunx resume alice
xunx upgrade --all
xunx user-list
子命令¶
| 子命令 | 作用 |
|---|---|
user-add <user> |
添加用户,生成随机令牌并打印一次 |
user-del <user> |
删除用户及其令牌,并尽力移除其容器 |
user-list |
列出用户名与令牌 |
serve |
运行多用户网关 |
pause <user> / resume <user> |
暂停 / 恢复容器(不丢弃状态,走网关地址) |
upgrade [user …] / --all |
打标记,下一次对账时用当前镜像重建容器 |
shell <user> |
进入用户容器的 shell 或执行指定命令 |
serve 的参数¶
| 参数 | 默认 | 说明 |
|---|---|---|
--host |
0.0.0.0 |
网关监听地址 |
--port |
18960 |
网关对外端口;0 由系统分配 |
--port-range |
17960-18959 |
分配给用户容器的宿主端口区间,必须与 --port 互斥 |
--image |
xun |
镜像;区间内会按 用户-实例 校验镜像可用性 |
--env |
[] |
与 xunc --env 同一套转发逻辑 |
生命周期与注意点¶
serve每 5 秒对账一次:该用户在跑就转发到它的地址;该用户在但容器没了就重建; 不该存在的容器(用户已删、镜像已换、--image变了)会被停掉并删除。serve的令牌与用户令牌都会缓存 10 秒(正负缓存都算),user-add后最多等这么久生效。pause只 stop 不 rm,resume再 start;user-del与配置变化触发的回收是 rm 级别。- 容器是临时实例:
xunx停止不会停容器,但 Docker 守护进程重启或xunx upgrade会移除它们。 - 网关会按
Xun-Auth头或?token=校验,用户令牌是 44 字符 urlsafe 串(正好等于内部会话令牌长度), 因此可以直接把网关 URL 交给用户。 user-add、user-list、user-del只读写$XUN_HOME/x/xunx.db,不要求serve在跑。
镜像里有什么¶
docker/Dockerfile 多阶段构建出一个带完整工具链的运行时:Python 虚拟环境(从 pyproject.toml 解析依赖)、
Node 与前端产物、Playwright 浏览器(含系统依赖与中文字体)、Rust 工具链、ffmpeg / Git / ripgrep 等常用命令,
以及一个专用非 root 用户。镜像内 ENV XUN_HOME=/.xun、XUN_INFO_TOOL_OVERRIDE=1,
启动命令是 xuns --host 0.0.0.0 --manage-sessions .。
容器以 --cap-drop ALL 启动,xunc 不额外加固;需要更强的隔离请自行叠加资源与网络限制。
相关入口¶
- 容器里跑的其实就是 xun / xuns 的会话。
- 想在容器里跑扩展命令:
xunc --exec "xune stat …",见 扩展 CLI 入口 xune。