feat(sandbox): Docker 后端改为会话级长驻容器,对齐 E2B 语义 - #59
Draft
lyingbug wants to merge 5 commits into
Draft
Conversation
现有 docker 后端每次执行都是一次性 docker run --rm,没有会话状态、超时不终止负载、 工作目录只读,与 E2B 后端不是能力差异而是模型差异。 新增一份直接打 Docker Engine API 的 PoC(29 项检查全过)验证:容器可承载 RemoteSandboxClient 的全部方法,commit 可承载空间级快照与增量更新;同时复现 Docker 无法对齐的部分(无空闲 TTL、客户端取消不杀进程、快照不含内存态、 CapDrop 后 root 越不过权限位、kill docker run 会留下在跑的容器)。 调研结论与落地建议见 docs/sandbox-docker-backend.md。 Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
把 docker 从一次性 `docker run --rm` 重写为 RemoteSandboxClient 适配器,
直接走 Docker Engine API,一个会话一个长驻容器,因此 shell_exec、附件暂存、
产物收集这些会话级能力对 docker 与 E2B 一致。
- Create/Connect/Get/List/Delete 映射到容器生命周期,metadata 落为 labels;
Connect 会重启被停掉的容器,保住会话文件系统
- Exec 用容器内 timeout(1) 包裹:客户端取消不会终止容器内进程
- 文件面走 archive API,mkdir/rm/ls 用 exec 补齐(Engine API 无对应接口)
- daemon 没有空闲 TTL,新增按活跃标记文件回收的限流清扫
- 镜像即模板:ListTemplates/EnsureStandardTemplate 走镜像列举与后台拉取
- 租户配置新增 host/TLS/CPU/内存/PID/网络/runtime/空闲 TTL 字段
- 标准镜像预建并授权 /workspace/{input,output}
针对真实 daemon 的一致性测试(-tags=docker_integration)覆盖会话状态、
包安装存活、shell_exec 复用沙箱、附件与产物、超时真实终止进程、
容器被外部停掉后恢复。
Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
新增 daemon 地址、TLS 证书目录、空闲回收、CPU/内存/进程数上限、网络模式字段, 并把 docker 已经是会话级后端这件事同步到各处文档。 Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
沙箱连通性检查用 curl 探测出网,而标准镜像里没有它——docker 后端每次完整验证 都会以「curl: not found」失败。文档一直把 curl 列在镜像内置工具里,这里让镜像 与文档一致。 Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
空闲清扫按活跃标记文件的 mtime 判断容器是否闲置,而技能脚本以非 root 的沙箱账号 执行。标记由容器入口创建并 chmod 666,否则在 umask 022 的宿主机上,只跑脚本的会话 会被判成从未活动、在用户正用着的时候被回收。 一致性测试直接以沙箱账号 exec 并断言标记权限与 mtime 推进,不再依赖 「每次执行前恰好有一次 root 操作」这一隐式耦合。 Co-authored-by: lyingbug <lyingbug@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
原来的
docker后端每次执行都是docker run --rm加一个只读 bind mount,和 E2B 不是「能力少一点」而是模型不同:没有会话状态,
shell_exec、附件暂存、产物收集在能力矩阵里根本不注册;超时 kill 的只是 CLI 客户端进程,容器还在跑;
/workspace只读,而 skills 框架恰恰要往/workspace/output写。本 PR 把它重写为
RemoteSandboxClient适配器:一个会话一个长驻容器,直接打 Docker Engine API。session→sandbox 绑定、生命周期锁、能力矩阵、产物收集一行没改——这正是当初抽出这层的收益。
调研过程与「Docker 到底能不能做到」的实测证据保留在
docs/poc/docker-sandbox(独立 go module,不参与主构建)。实现要点
Connect会重启被停掉的容器——文件系统还在,会话就能接着用(对应 E2B 的 auto-resume)。timeout(1)执行:取消 HTTP 请求不会终止容器里的进程。命令通过位置参数(
sh -c '…' weknora-exec "$@") 传入,不做字符串拼接,脚本里的引号和换行不会改变实际执行的东西。touch一个活跃标记文件,清扫时一次HEAD /archive读 mtime 即可判断闲置,无需额外 exec 或 Redis 记账;按 daemon 端点限流、后台执行;每个容器把创建时的 TTL 记在 label 上,避免 A 配置的清扫拿自己的 TTL 衡量 B 配置的容器。
mkdir/rm/ls用 exec 补齐(Engine API 无对应接口)。CapDrop: ALL+ 仅补回 root 装包所需的 7 个 cap、no-new-privileges、内存/CPU/PID 上限、swap 关闭;远程 daemon 走 mTLS,证书按路径引用不入库;daemon 地址过 SSRF 校验。
ListTemplates/EnsureStandardTemplate走镜像列举与后台拉取,设置页流程不变。/workspace/{input,output},并补上curl(连通性检查用它探测出网,文档一直声称镜像里有)。边界(写进文档,不是遗漏)
跨主机调度、内核级隔离、内存态快照、域名级出网策略、卷挂载都不在这个后端的能力范围内,
需要这些仍应使用 E2B 协议后端。
验证
真实 daemon 一致性测试(与 E2B 一致性测试断言同一批语义):
端到端 UI:在本地跑起 WeKnora(Lite),新建 Docker 沙箱后端并执行「完整验证」,
五项全绿(含在真实容器里执行命令与出网探测)。
docker_sandbox_backend_deep_check_all_pass.mp4
Docker 后端的运行参数
完整验证五项全绿
单元测试用内存版 Engine API 驱动适配器(不需要 daemon);
go vet+ 全量go test、前端
type-check与 i18n 审计均通过。To show artifacts inline, enable in settings.