refactor(box): run Box Runtime as subprocess inside LangBot container

Remove the separate langbot_box_runtime Docker service. Box Runtime
  now always launches as a local stdio subprocess, regardless of whether
  LangBot runs in Docker or not. The WebSocket transport path is kept
  only for explicit runtime_url configuration (remote deployment).

  This simplifies deployment by eliminating cross-container path mapping
  and network hops. Box Runtime is a pure scheduling process (talks to
  Docker socket / nsjail), it does not execute user code or touch the
  filesystem, so container isolation is unnecessary — unlike Plugin
  Runtime.
This commit is contained in:
youhuanghe
2026-04-09 12:14:23 +00:00
committed by WangCham
parent a8eb6e6984
commit 2697d82286
4 changed files with 12 additions and 35 deletions

View File

@@ -4,24 +4,6 @@ version: "3"
services:
langbot_box_runtime:
image: rockchin/langbot:latest
container_name: langbot_box_runtime
command: ["uv", "run", "--no-sync", "-m", "langbot_plugin.box.server"]
volumes:
# Mount the container runtime socket from the host.
# Uncomment the one that matches your container runtime:
# - /var/run/podman/podman.sock:/var/run/podman/podman.sock # Podman
- /var/run/docker.sock:/var/run/docker.sock # Docker
- ./data/box:/workspaces
ports:
- 5410:5410
restart: on-failure
environment:
- TZ=Asia/Shanghai
networks:
- langbot_network
langbot_plugin_runtime:
image: rockchin/langbot:latest
container_name: langbot_plugin_runtime
@@ -42,6 +24,10 @@ services:
volumes:
- ./data:/app/data
- ./data/box:/workspaces
# Mount container runtime socket for Box sandbox (Docker backend).
# Uncomment the one that matches your container runtime:
# - /var/run/podman/podman.sock:/var/run/podman/podman.sock # Podman
- /var/run/docker.sock:/var/run/docker.sock # Docker
restart: on-failure
environment:
- TZ=Asia/Shanghai

View File

@@ -12,7 +12,6 @@ from langbot_plugin.runtime.io.connection import Connection
from langbot_plugin.box.client import ActionRPCBoxClient
from langbot_plugin.box.errors import BoxRuntimeUnavailableError
from ..utils import platform
if TYPE_CHECKING:
from ..core import app as core_app
@@ -31,8 +30,6 @@ def resolve_box_ws_relay_url(ap: core_app.Application) -> str:
if runtime_url:
return runtime_url
if platform.get_platform() == 'docker':
return 'http://langbot_box_runtime:5410'
return 'http://127.0.0.1:5410'
@@ -160,4 +157,4 @@ class BoxRuntimeConnector:
return str(_get_box_config(self.ap).get('runtime_url', '')).strip()
def _should_manage_local_runtime(self) -> bool:
return not self.configured_runtime_url and platform.get_platform() != 'docker'
return not self.configured_runtime_url

View File

@@ -89,7 +89,7 @@ monitoring:
check_interval_hours: 1
box:
profile: 'default'
runtime_url: '' # Leave empty to use defaults: http://127.0.0.1:5410 locally, http://langbot_box_runtime:5410 in Docker
runtime_url: '' # Leave empty to auto-launch local Box Runtime subprocess. Set to a URL only for remote/external deployment.
shared_host_root: './data/box' # For Docker deployment, use '/workspaces'
default_host_workspace: '' # Defaults to '<shared_host_root>/default'
allowed_host_mount_roots: # Defaults to ['<shared_host_root>'] when left empty

View File

@@ -25,12 +25,7 @@ def make_app(logger: Mock, runtime_url: str = ''):
)
def patch_platform(monkeypatch: pytest.MonkeyPatch, value: str):
monkeypatch.setattr('langbot.pkg.box.connector.platform.get_platform', lambda: value)
def test_box_runtime_connector_manages_local_when_no_url(monkeypatch: pytest.MonkeyPatch):
patch_platform(monkeypatch, 'linux')
def test_box_runtime_connector_manages_local_when_no_url():
connector = BoxRuntimeConnector(make_app(Mock()))
assert connector.manages_local_runtime is True
@@ -45,16 +40,15 @@ def test_box_runtime_connector_remote_when_url_configured():
assert isinstance(connector.client, ActionRPCBoxClient)
def test_box_runtime_connector_remote_when_docker(monkeypatch: pytest.MonkeyPatch):
patch_platform(monkeypatch, 'docker')
def test_box_runtime_connector_manages_local_in_docker(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr('langbot.pkg.utils.platform.get_platform', lambda: 'docker')
connector = BoxRuntimeConnector(make_app(Mock()))
assert connector.manages_local_runtime is False
assert connector.ws_relay_base_url == 'http://langbot_box_runtime:5410'
assert connector.manages_local_runtime is True
assert connector.ws_relay_base_url == 'http://127.0.0.1:5410'
def test_box_runtime_connector_ws_relay_url_default(monkeypatch: pytest.MonkeyPatch):
patch_platform(monkeypatch, 'linux')
def test_box_runtime_connector_ws_relay_url_default():
connector = BoxRuntimeConnector(make_app(Mock()))
assert connector.ws_relay_base_url == 'http://127.0.0.1:5410'