Docker 运行时
worker-docker 是默认的 worker 类型,通过创建和管理 Docker 容器来隔离执行代码。
适用场景
- 通用的沙箱代码执行
- 宿主机已安装 Docker
- 希望使用成熟的容器技术
工作原理
- Worker 通过 gRPC 连接控制节点。
- 收到执行请求后,worker 拉取或复用镜像并启动容器。
- 代码在资源受限的容器内运行。
- 输出通过控制面流式返回。
对于 terminalResource 的 validate/read/export,worker 会通过 docker exec <container> python3 -c ... 探测文件元数据,因此 terminal 执行镜像必须提供 python3。
前置条件
- Docker Engine
- 能够访问控制节点 gRPC 端口
启动 worker
从 GitHub Releases 页面 下载对应版本的 worker-docker 二进制文件,然后运行:
WORKER_CONSOLE_GRPC_TARGET=<console_grpc_target> \
WORKER_ID=<worker_id> \
WORKER_SECRET=<worker_secret> \
./onlyboxes-worker-docker通过非 TLS 连接时请设置 WORKER_CONSOLE_INSECURE=true。
配置文件
Dashboard 中的 Worker 启动工具可以生成并下载可直接使用的 config.toml。设置 WORKER_CONFIG_FILE 可以显式指定配置文件;未设置时,worker 会依次查找程序文件同目录和当前工作目录下的 config.toml。
配置优先级为:环境变量 > config.toml > 内置默认值。TOML 键名由环境变量名移除 WORKER_ 前缀并转换为小写得到,例如 WORKER_TERMINAL_EXEC_DOCKER_IMAGE 对应 terminal_exec_docker_image。Worker 标签使用 [labels] 表配置。
id = "wk_..."
secret = "..."
console_grpc_target = "console.internal:50051"
terminal_exec_docker_image = "coolfan1024/onlyboxes-runtime:default"
terminal_max_active_sessions = 0
[labels]
region = "cn"全部可用配置请参考带注释的配置模板。
环境变量
连接
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WORKER_CONSOLE_GRPC_TARGET | 否 | 127.0.0.1:50051 | 控制节点 gRPC 地址 |
WORKER_CONSOLE_INSECURE | 否 | false | 设为 true 允许不安全的连接(非 TLS) |
WORKER_ID | 是 | Dashboard 中的 Worker ID | |
WORKER_SECRET | 是 | 创建 worker 时的一次性密钥 |
身份
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WORKER_NODE_NAME | 否 | 可读的节点名称 | |
WORKER_VERSION | 否 | 构建版本 | 上报给控制节点的版本号 |
WORKER_LABELS | 否 | CSV 格式标签,如 region=us,owner=team-a |
Docker 镜像
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WORKER_PYTHON_EXEC_DOCKER_IMAGE | 否 | ghcr.io/astral-sh/uv:python3.12-bookworm-slim | Python 执行镜像 |
WORKER_TERMINAL_EXEC_DOCKER_IMAGE | 否 | coolfan1024/onlyboxes-runtime:default | 终端执行镜像 |
terminalExec和terminalResource都依赖 terminal 执行镜像。如果该镜像不包含python3,文件探针会在校验、读取或导出元数据之前失败。
默认终端镜像是通用执行镜像,包含 Python 3、Node.js 24、npm、Corepack、常用 shell/文件工具、轻量文档处理库,以及基于 Lightpanda 的 agent-browser。LobeHub 专用 sandbox 工具链请使用 coolfan1024/onlyboxes-runtime:lobehub。
Docker 网络
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WORKER_DOCKER_NETWORK | 否 | terminalExec 与 pythonExec 容器使用的隔离 bridge |
配置后,Worker 会在连接 Console 前检查该网络:
- 网络不存在时,使用
bridgedriver 创建网络,并设置com.docker.network.bridge.enable_icc=false;创建完成后再次检查。 - 网络已存在时,检查 driver 必须为
bridge,且com.docker.network.bridge.enable_icc必须明确为false。 - Docker inspect/create 执行失败、创建后仍找不到网络、driver 不匹配或 ICC 未关闭时,Worker 会直接启动失败,不会注册到 Console,也不会回退到 Docker 默认网络。
校验通过后,terminal 容器的创建、IP 读取、Session 恢复以及 pythonExec 容器创建都会使用该网络。需要指定 subnet 或 gateway 时,应先由管理员创建网络:
docker network create \
--driver bridge \
--subnet 172.28.0.0/16 \
--gateway 172.28.0.1 \
--opt com.docker.network.bridge.enable_icc=false \
onlyboxes-sandbox-custom未配置时保持原有行为:关闭公开预览时,terminalExec 与 pythonExec 都使用 Docker 默认网络;开启公开预览时,仅 terminalExec 使用自动管理的 onlyboxes-sandbox,pythonExec 仍使用 Docker 默认网络。修改网络配置前应结束该 Worker 上的现存 terminal sessions,否则旧容器无法从新网络恢复。
执行资源
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WORKER_PYTHON_EXEC_MEMORY_MIB | 否 | 256 | pythonExec 容器的内存限制,单位 MiB |
WORKER_PYTHON_EXEC_CPUS | 否 | 1.0 | pythonExec 容器的 CPU 限制 |
WORKER_PYTHON_EXEC_MAX_PROCESSES | 否 | 128 | pythonExec 容器的最大进程 / task 数 |
WORKER_TERMINAL_EXEC_MEMORY_MIB | 否 | 256 | terminalExec 容器的内存限制,单位 MiB |
WORKER_TERMINAL_EXEC_CPUS | 否 | 1.0 | terminalExec 容器的 CPU 限制 |
WORKER_TERMINAL_EXEC_MAX_PROCESSES | 否 | 128 | terminalExec 容器的最大进程 / task 数 |
并发上限
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WORKER_ECHO_MAX_INFLIGHT | 否 | 4 | echo 最大并发数 |
WORKER_PYTHON_EXEC_MAX_INFLIGHT | 否 | 4 | pythonExec 最大并发数 |
WORKER_TERMINAL_EXEC_MAX_INFLIGHT | 否 | 4 | terminalExec 最大并发数 |
WORKER_TERMINAL_RESOURCE_MAX_INFLIGHT | 否 | 4 | terminalResource 最大并发数 |
WORKER_TERMINAL_SESSION_MAX_INFLIGHT | 否 | 1 | 单个 terminal session 的最大并发数;terminalExec 与 terminalResource 共享 |
WORKER_TERMINAL_MAX_ACTIVE_SESSIONS | 否 | 0(无限制) | 当前 worker 进程管理的 terminal session 数量上限 |
WORKER_TERMINAL_EXEC_MAX_INFLIGHT 和 WORKER_TERMINAL_RESOURCE_MAX_INFLIGHT 分别限制整个 worker 上对应能力的并发数,二者相互独立,没有额外的 worker 全局合计上限。WORKER_TERMINAL_SESSION_MAX_INFLIGHT 则限制单个 session_id,并将 terminalExec 与 terminalResource 合并计数。请求必须同时满足对应能力上限和 session 上限。
WORKER_TERMINAL_MAX_ACTIVE_SESSIONS 是独立的 session 数量上限。0 表示不限制;正数会统计创建中、可用、等待执行中命令结束以及 Docker cleanup 进行中的 session。容量已满时已有 session 仍可使用,新建 session 返回 429 session_capacity_exceeded。负数或非法值回退为 0。
例如将 terminalExec 和 terminalResource 上限都设为 10、单 session 上限设为 2 时,整个 worker 最多可同时处理 10 个 terminalExec 和 10 个 terminalResource,但任一 session 内两类操作合计不能超过 2。超出单 session 上限返回 409 session_busy,对应能力的 worker 级并发额度耗尽返回 429 no_capacity,新建 session 时 session 数量上限耗尽返回 429 session_capacity_exceeded。
终端租约
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WORKER_TERMINAL_LEASE_MIN_SEC | 否 | 60 | 最短租约时长(秒) |
WORKER_TERMINAL_LEASE_MAX_SEC | 否 | 1800 | 最长租约时长(秒) |
WORKER_TERMINAL_LEASE_DEFAULT_SEC | 否 | 60 | 默认租约时长(秒) |
WORKER_TERMINAL_OUTPUT_LIMIT_BYTES | 否 | 1048576 | 每个流的输出上限(字节) |
WORKER_TERMINAL_EXPORT_MAX_BYTES | 否 | 0(无限制) | export action 最大文件大小(字节),0 为无限制 |
Worker 会声明仅供 Console 内部使用的 terminalLeaseRenew 能力。它接收 {"session_id":"required","lease_ttl_sec":300},以单调方式延长已有租约、重置 session 租约计时器,并在不执行命令的情况下返回确认后的绝对到期时间。该能力拥有独立的 max_inflight,其声明值取自 WORKER_TERMINAL_EXEC_MAX_INFLIGHT 配置。
心跳
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WORKER_HEARTBEAT_INTERVAL_SEC | 否 | 5 | 心跳间隔(秒) |
WORKER_HEARTBEAT_JITTER_PCT | 否 | 20 | 抖动百分比(0–100) |
WORKER_CALL_TIMEOUT_SEC | 否 | ceil(2.5 * interval) | gRPC 调用超时(秒) |
日志
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
WORKER_LOG_LEVEL | 否 | info | debug / info / warn / error |
WORKER_LOG_FORMAT | 否 | json | json / text |
WORKER_LOG_ADD_SOURCE | 否 | false | 是否在日志中包含源文件和行号 |