Docker Runtime

worker-docker is the default worker type. It creates and manages Docker containers to execute code in isolated sandboxes.

When to use

  • General-purpose sandboxed code execution
  • You already have Docker installed on the host
  • You want to use mature container technology

How it works

  1. The worker connects to the control node over gRPC.
  2. When an execution request arrives, the worker pulls or reuses an image and starts a container.
  3. Code runs inside the container with resource limits applied.
  4. Output is streamed back through the control plane.

For terminalResource validate/read/export operations, the worker probes file metadata via docker exec <container> python3 -c ..., so the terminal execution image must provide python3.

Prerequisites

  • Docker Engine
  • Network access to the control node gRPC endpoint

Starting the worker

Download the matching version of the worker-docker binary from the GitHub releases page, then run:

WORKER_CONSOLE_GRPC_TARGET=<console_grpc_target> \
WORKER_ID=<worker_id> \
WORKER_SECRET=<worker_secret> \
./onlyboxes-worker-docker

Set WORKER_CONSOLE_INSECURE=true when connecting without TLS.

Configuration file

The Worker Startup Tool in the dashboard can generate and download a ready-to-use config.toml. Set WORKER_CONFIG_FILE to use a specific file. If it is not set, the worker looks for config.toml next to the worker binary and then in the current working directory.

Environment variables take precedence over config.toml, which takes precedence over built-in defaults. TOML keys use the environment variable name without the WORKER_ prefix and in lowercase; for example, WORKER_TERMINAL_EXEC_DOCKER_IMAGE becomes terminal_exec_docker_image. Use a [labels] table for 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 = "us"

See the annotated configuration template for all available keys.

Environment variables

Connection

VariableRequiredDefaultDescription
WORKER_CONSOLE_GRPC_TARGETNo127.0.0.1:50051Control node gRPC address
WORKER_CONSOLE_INSECURENofalseSet true to allow insecure connections (non-TLS)
WORKER_IDYesWorker ID from the dashboard
WORKER_SECRETYesOne-time secret from worker creation

Identity

VariableRequiredDefaultDescription
WORKER_NODE_NAMENoHuman-readable node name
WORKER_VERSIONNobuild versionVersion reported to console
WORKER_LABELSNoCSV labels, e.g. region=us,owner=team-a

Docker images

VariableRequiredDefaultDescription
WORKER_PYTHON_EXEC_DOCKER_IMAGENoghcr.io/astral-sh/uv:python3.12-bookworm-slimImage for Python execution
WORKER_TERMINAL_EXEC_DOCKER_IMAGENocoolfan1024/onlyboxes-runtime:defaultImage for terminal execution

terminalExec and terminalResource both rely on the terminal execution image. If that image does not include python3, file probe operations will fail before metadata can be validated or exported.

The default terminal image is a general execution image with Python 3, Node.js 24, npm, Corepack, common shell/file utilities, lightweight document helpers, and agent-browser with Lightpanda. Use coolfan1024/onlyboxes-runtime:lobehub for LobeHub-specific sandbox tooling.

Docker network

VariableRequiredDefaultDescription
WORKER_DOCKER_NETWORKNoIsolated bridge used by terminalExec and pythonExec containers

When configured, the Worker checks the network before connecting to Console:

  • If the network does not exist, the Worker creates it with the bridge driver and com.docker.network.bridge.enable_icc=false, then verifies it again.
  • If the network already exists, its driver must be bridge and com.docker.network.bridge.enable_icc must explicitly be false.
  • If Docker inspect/create fails, the network is still missing after creation, the driver does not match, or ICC is enabled, Worker startup fails. It does not register with Console or fall back to Docker's default network.

After validation succeeds, terminal container creation, IP inspection, session recovery, and pythonExec container creation all use this network. To select a specific subnet or gateway, pre-create the network as an administrator:

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

When unset, existing behavior is preserved: with public preview disabled, terminalExec and pythonExec use Docker's default network; with public preview enabled, only terminalExec joins the automatically managed onlyboxes-sandbox bridge while pythonExec stays on Docker's default network. End existing terminal sessions on this Worker before changing the network, because containers attached to the old network cannot be recovered through the new one.

Execution resources

VariableRequiredDefaultDescription
WORKER_PYTHON_EXEC_MEMORY_MIBNo256Memory limit for pythonExec containers in MiB
WORKER_PYTHON_EXEC_CPUSNo1.0CPU limit for pythonExec containers
WORKER_PYTHON_EXEC_MAX_PROCESSESNo128Max process / task count for pythonExec containers
WORKER_TERMINAL_EXEC_MEMORY_MIBNo256Memory limit for terminalExec containers in MiB
WORKER_TERMINAL_EXEC_CPUSNo1.0CPU limit for terminalExec containers
WORKER_TERMINAL_EXEC_MAX_PROCESSESNo128Max process / task count for terminalExec containers

Concurrency

VariableRequiredDefaultDescription
WORKER_ECHO_MAX_INFLIGHTNo4Max concurrent echo commands
WORKER_PYTHON_EXEC_MAX_INFLIGHTNo4Max concurrent pythonExec commands
WORKER_TERMINAL_EXEC_MAX_INFLIGHTNo4Max concurrent terminalExec commands
WORKER_TERMINAL_RESOURCE_MAX_INFLIGHTNo4Max concurrent terminalResource commands
WORKER_TERMINAL_SESSION_MAX_INFLIGHTNo1Max concurrent operations in one terminal session; shared by terminalExec and terminalResource
WORKER_TERMINAL_MAX_ACTIVE_SESSIONSNo0 (unlimited)Maximum terminal sessions managed by this worker process

WORKER_TERMINAL_EXEC_MAX_INFLIGHT and WORKER_TERMINAL_RESOURCE_MAX_INFLIGHT independently limit their respective capabilities across the worker; there is no additional aggregate worker-wide limit. WORKER_TERMINAL_SESSION_MAX_INFLIGHT applies to one session_id and counts terminalExec and terminalResource together. A request must satisfy both its capability limit and the session limit.

WORKER_TERMINAL_MAX_ACTIVE_SESSIONS is a separate session-count limit. 0 leaves the count unlimited; a positive value counts sessions that are being created, ready, waiting for in-flight commands to drain, or undergoing Docker cleanup. Existing sessions remain usable when the limit is full, while a new session returns 429 session_capacity_exceeded. Negative or invalid values fall back to 0.

For example, with both capability limits set to 10 and the per-session limit set to 2, the worker can process up to 10 terminalExec and 10 terminalResource operations at once, while any one session can run at most two operations in total. Exceeding the per-session limit returns 409 session_busy; exhausting a capability's worker-wide concurrency returns 429 no_capacity; exhausting the session-count limit while creating a session returns 429 session_capacity_exceeded.

Terminal lease

VariableRequiredDefaultDescription
WORKER_TERMINAL_LEASE_MIN_SECNo60Minimum lease duration (seconds)
WORKER_TERMINAL_LEASE_MAX_SECNo1800Maximum lease duration (seconds)
WORKER_TERMINAL_LEASE_DEFAULT_SECNo60Default lease duration (seconds)
WORKER_TERMINAL_OUTPUT_LIMIT_BYTESNo1048576Output limit per stream (bytes)
WORKER_TERMINAL_EXPORT_MAX_BYTESNo0 (unlimited)Maximum file size in bytes for export action; 0 disables the limit

The Worker advertises terminalLeaseRenew as an internal Console-only capability. It accepts {"session_id":"required","lease_ttl_sec":300}, extends an existing lease monotonically, resets the session lease timer, and returns the confirmed absolute expiry without executing a command. Its independent max_inflight declaration uses the configured WORKER_TERMINAL_EXEC_MAX_INFLIGHT value.

Heartbeat

VariableRequiredDefaultDescription
WORKER_HEARTBEAT_INTERVAL_SECNo5Heartbeat interval (seconds)
WORKER_HEARTBEAT_JITTER_PCTNo20Jitter percentage (0–100)
WORKER_CALL_TIMEOUT_SECNoceil(2.5 * interval)gRPC call timeout (seconds)

Logging

VariableRequiredDefaultDescription
WORKER_LOG_LEVELNoinfodebug / info / warn / error
WORKER_LOG_FORMATNojsonjson / text
WORKER_LOG_ADD_SOURCENofalseInclude source file and line