diff --git a/backend/docs/CONFIGURATION.md b/backend/docs/CONFIGURATION.md index fd2091c51..a2e8561f8 100644 --- a/backend/docs/CONFIGURATION.md +++ b/backend/docs/CONFIGURATION.md @@ -303,6 +303,55 @@ When you configure `sandbox.mounts`, DeerFlow exposes those `container_path` val For bare-metal Docker sandbox runs that use localhost, DeerFlow binds the sandbox HTTP port to `127.0.0.1` by default so it is not exposed on every host interface. Docker-outside-of-Docker deployments that connect through `host.docker.internal` keep the broad legacy bind for compatibility. Set `DEER_FLOW_SANDBOX_BIND_HOST` explicitly if your deployment needs a different bind address. +### Building a Custom AIO Sandbox Image + +`AioSandboxProvider` talks to the sandbox container through the `agent-sandbox` SDK. The Dockerfile for the default `enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest` image is not part of this repository; DeerFlow treats that image as an upstream AIO sandbox runtime. + +For persistent system or language dependencies, extend the published image and keep its startup command intact: + +```dockerfile +FROM enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest + +USER root +# Example user dependency; not required by DeerFlow itself. +RUN apt-get update \ + && apt-get install -y --no-install-recommends graphviz \ + && rm -rf /var/lib/apt/lists/* + +# Example Python dependency for work done inside the sandbox. +RUN python -m pip install --no-cache-dir pandas + +# Do not override ENTRYPOINT or CMD; keep the upstream sandbox server startup. +``` + +Use the custom image in local Docker or Apple Container mode with `sandbox.image`: + +```yaml +sandbox: + use: deerflow.community.aio_sandbox:AioSandboxProvider + image: your-registry/your-aio-sandbox:tag +``` + +In provisioner mode, sandbox Pods are created by the provisioner service, so configure the provisioner `SANDBOX_IMAGE` environment variable instead of `sandbox.image`. See the [Provisioner Setup Guide](../../docker/provisioner/README.md#custom-sandbox-image). + +If you rebuild the runtime from scratch instead of extending the published image, it must expose the same HTTP API used by `agent-sandbox`. DeerFlow currently depends on: + +- `sandbox.get_context()`, including `home_dir` +- `shell.exec_command(...)` +- `file.read_file(...)` +- `file.write_file(...)`, including base64 writes for binary content +- streamed `file.download_file(...)` +- `file.find_files(...)` +- `file.list_path(...)` +- `file.search_in_file(...)` + +Custom images must also keep these compatibility constraints: + +- The container should listen on the configured sandbox port, `8080` by default. +- `/mnt/user-data` must remain writable because DeerFlow mounts thread workspace, uploads, and outputs there. +- `home_dir` comes from the sandbox context endpoint; do not assume DeerFlow hardcodes it. +- Shell command handling must remain compatible with serialized `exec_command` calls. DeerFlow serializes shell access on the host side to avoid corrupting the sandbox's persistent shell session. + ### Skills Configure the skills directory for specialized workflows: diff --git a/config.example.yaml b/config.example.yaml index 5f9ff9a82..e20ce5443 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -832,6 +832,8 @@ sandbox: # # Optional: Container image to use (works with both Docker and Apple Container) # # Default: enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest # # Recommended: enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest (works on both x86_64 and arm64) +# # Custom images should extend the default image or implement the same AIO +# # sandbox HTTP API used by agent-sandbox. See backend/docs/CONFIGURATION.md. # # image: enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest # # # Optional: Base port for sandbox containers (default: 8080) @@ -870,6 +872,8 @@ sandbox: # sandbox: # use: deerflow.community.aio_sandbox:AioSandboxProvider # provisioner_url: http://provisioner:8002 +# # Note: provisioner-created Pods use the provisioner's SANDBOX_IMAGE +# # environment variable, not sandbox.image from this config file. # ============================================================================ # Subagents Configuration diff --git a/docker/provisioner/README.md b/docker/provisioner/README.md index 36251da17..6144bda1d 100644 --- a/docker/provisioner/README.md +++ b/docker/provisioner/README.md @@ -137,7 +137,7 @@ The provisioner is configured via environment variables (set in [docker-compose- | Variable | Default | Description | |----------|---------|-------------| | `K8S_NAMESPACE` | `deer-flow` | Kubernetes namespace for sandbox resources | -| `SANDBOX_IMAGE` | `enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest` | Container image for sandbox Pods | +| `SANDBOX_IMAGE` | `enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest` | AIO-compatible container image for sandbox Pods | | `SKILLS_HOST_PATH` | - | **Host machine** path to skills directory (must be absolute) | | `THREADS_HOST_PATH` | - | **Host machine** path to threads data directory (must be absolute) | | `SKILLS_PVC_NAME` | empty (use hostPath) | PVC name for skills volume; when set, sandbox Pods use PVC instead of hostPath | @@ -146,6 +146,14 @@ The provisioner is configured via environment variables (set in [docker-compose- | `NODE_HOST` | `host.docker.internal` | Hostname that backend containers use to reach host NodePorts | | `K8S_API_SERVER` | (from kubeconfig) | Override K8s API server URL (e.g., `https://host.docker.internal:26443`) | +### Custom sandbox image + +Provisioner-created sandbox Pods use the provisioner's `SANDBOX_IMAGE` environment variable. This is separate from `sandbox.image` in `config.yaml`, which applies to local Docker or Apple Container mode. + +For persistent dependencies, build an image that extends the default `all-in-one-sandbox` image and set `SANDBOX_IMAGE` to your published tag. A from-scratch image must remain compatible with the AIO sandbox HTTP API consumed by `agent-sandbox`, keep `/mnt/user-data` writable, and listen on the configured sandbox port. + +See [Building a Custom AIO Sandbox Image](../../backend/docs/CONFIGURATION.md#building-a-custom-aio-sandbox-image) for the runtime contract and a minimal Dockerfile example. + ### PVC User-Data Upgrade Note Older provisioner versions mounted PVC user-data from `threads/{thread_id}/user-data`. The user-scoped layout mounts from `deer-flow/users/{user_id}/threads/{thread_id}/user-data`.