mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-17 05:31:16 +08:00
Previously, Docker was auto-detected when the CLI was installed or a candidate Unix socket existed. Neither check verified that the Docker API was responsive. A similar check was done when auto-detecting Podman in the past, but was replaced in1f07bf04with a probe of candidate Podman sockets instead. This change applies the functional API probing approach introduced for Podman in1f07bf04to Docker. It also makes Docker driver initialization use the same socket-selection mechanism as Docker auto-detection instead of Bollard’s local defaults. This means the previously auto-detectable Docker socket paths $HOME/.docker/run/docker.sock and $XDG_RUNTIME_DIR/docker.sock will actually be usable. When no working compute driver can be auto-detected, the gateway exits early with a message saying as much: > configuration error: no compute driver configured and auto-detection found no > suitable driver; set --drivers or OPENSHELL_DRIVERS to kubernetes, podman, > docker, or vm This makes for a better user experience when installing OpenShell without an available supported compute driver. Signed-off-by: Kris Hicks <khicks@nvidia.com>
133 lines
6.2 KiB
Markdown
133 lines
6.2 KiB
Markdown
# openshell-driver-docker
|
|
|
|
Docker-backed compute driver for local OpenShell gateways.
|
|
|
|
The driver manages sandbox containers through the local Docker daemon with the
|
|
`bollard` client. It is intended for developer environments where Docker is
|
|
already available and running Kubernetes would be unnecessary.
|
|
|
|
The driver connects to `[openshell.drivers.docker].socket_path` when configured.
|
|
Otherwise, it uses the first standard local Docker socket that responds to an
|
|
API ping, which is the same selection mechanism used by gateway auto-detection.
|
|
An explicitly selected Docker driver falls back to `/var/run/docker.sock` when
|
|
no candidate responds.
|
|
|
|
## Runtime Model
|
|
|
|
The gateway runs as a host process. The Docker driver creates one container per
|
|
sandbox and starts the `openshell-sandbox` supervisor inside that container. The
|
|
supervisor then creates the nested sandbox namespace for the agent process.
|
|
|
|
Docker containers join an OpenShell-managed bridge network. The driver injects
|
|
`host.openshell.internal` and `host.docker.internal` so supervisors have stable
|
|
names for reaching the gateway host. On Docker Desktop, Colima, Rancher
|
|
Desktop, OrbStack, and macOS-hosted gateways, those names use Docker's
|
|
`host-gateway` alias. On native Linux Docker, the gateway also binds the bridge
|
|
gateway IP so containers can call back to the host process.
|
|
|
|
## Container Contract
|
|
|
|
The driver-controlled container settings are part of the sandbox security
|
|
contract:
|
|
|
|
| Setting | Purpose |
|
|
|---|---|
|
|
| `user = "0"` | The supervisor needs root inside the container to prepare namespaces, mounts, Landlock, and seccomp. |
|
|
| `network_mode = openshell` | Places the supervisor on the managed Docker bridge network. |
|
|
| `cap_add` | Grants supervisor-only capabilities required for namespace setup and process inspection. |
|
|
| `apparmor=unconfined` | Avoids Docker's default profile blocking required mount operations. |
|
|
| `restart_policy = unless-stopped` | Keeps managed sandboxes resumable across daemon or gateway restarts. |
|
|
| `PidsLimit` | Enforces the sandbox PID budget at the Docker cgroup layer. Set `[openshell.drivers.docker].sandbox_pids_limit = 0` to inherit the Docker/runtime default. |
|
|
| CDI GPU request | Uses opaque `driver_config.cdi_devices` values when set; otherwise selects the requested count of NVIDIA CDI GPUs in round-robin order when daemon CDI support is detected. Docker daemon `/info` can permit `nvidia.com/gpu=all` as a WSL2 all-only compatibility fallback, where it counts as one selectable device. Exact CDI device lists must not contain duplicates and must match the effective GPU count. |
|
|
|
|
The agent child process does not retain these supervisor privileges.
|
|
|
|
## Driver Config Mounts
|
|
|
|
The gateway forwards the `docker` block from `--driver-config-json` to this
|
|
driver. The driver accepts user-supplied `mounts` entries with these Docker
|
|
mount types:
|
|
|
|
- `bind`: mounts an absolute host path when `[openshell.drivers.docker]`
|
|
has `enable_bind_mounts = true`.
|
|
- `volume`: mounts an existing Docker named volume. The driver validates that
|
|
the volume exists before provisioning and never creates or removes it.
|
|
Docker local-driver volumes created with bind options are treated as host
|
|
bind mounts and require `enable_bind_mounts = true`.
|
|
- `tmpfs`: mounts an in-memory filesystem with optional `options`,
|
|
`size_bytes`, and `mode`.
|
|
|
|
Host bind mounts are disabled by default because they expose gateway host
|
|
paths to sandbox requests. Image mounts are not part of the Docker
|
|
driver-config schema. The driver still uses internal bind mounts for
|
|
OpenShell-owned supervisor, token, and TLS material.
|
|
|
|
Docker `bind` mounts accept `source`, `target`, optional `read_only`, and an
|
|
optional `selinux_label` of `shared` (applies `:z`) or `private` (applies
|
|
`:Z`) for SELinux-enforcing hosts. Docker `volume` mounts may include
|
|
`subpath`. User-supplied bind and volume mounts are read-only by default; set
|
|
`read_only: false` to make them writable. Mount `source`, `target`, and
|
|
`subpath` values must not contain surrounding whitespace. Mount targets must be
|
|
absolute container paths and must not replace the workspace root (`/sandbox`)
|
|
or overlap OpenShell supervisor files, `/etc/openshell`, `/etc/openshell-tls`,
|
|
or `/run/netns`.
|
|
|
|
Example named-volume usage:
|
|
|
|
```shell
|
|
docker volume create openshell-work
|
|
|
|
openshell sandbox create \
|
|
--driver-config-json '{"docker":{"mounts":[{"type":"volume","source":"openshell-work","target":"/sandbox/work"}]}}' \
|
|
-- claude
|
|
```
|
|
|
|
## Supervisor Binary Resolution
|
|
|
|
The Docker driver bind-mounts a host-side Linux `openshell-sandbox` binary into
|
|
each sandbox container. Resolution order is:
|
|
|
|
1. `supervisor_bin` in `[openshell.drivers.docker]`.
|
|
2. `supervisor_image` in `[openshell.drivers.docker]`, extracting
|
|
`/openshell-sandbox` from that image.
|
|
3. A sibling `openshell-sandbox` next to the running `openshell-gateway` binary.
|
|
4. A local Linux cargo target build for the Docker daemon architecture.
|
|
5. The release-matched default supervisor image, extracting `/openshell-sandbox`.
|
|
|
|
Release and Docker-image gateway builds bake the matching supervisor image tag
|
|
into the binary at compile time. The default Docker supervisor image is not
|
|
`:latest` unless a custom build explicitly sets that tag.
|
|
|
|
## Callback and TLS
|
|
|
|
`OPENSHELL_ENDPOINT` is injected from the gateway's configured gRPC endpoint.
|
|
When no endpoint is configured, the driver uses
|
|
`host.openshell.internal:<gateway-port>` with the appropriate HTTP or HTTPS
|
|
scheme. Set `host_gateway_ip` only when the host has an explicit, locally
|
|
assigned address that containers should use for callbacks; package-managed
|
|
macOS gateways should leave it unset.
|
|
|
|
For HTTPS endpoints, the server certificate must include the endpoint host as a
|
|
subject alternative name. Docker sandboxes also need the client TLS bundle
|
|
mounted into the container and exposed with:
|
|
|
|
- `OPENSHELL_TLS_CA`
|
|
- `OPENSHELL_TLS_CERT`
|
|
- `OPENSHELL_TLS_KEY`
|
|
|
|
HTTP endpoints reject TLS material because the supervisor would not use it.
|
|
|
|
## Environment Ownership
|
|
|
|
The driver merges template environment and sandbox spec environment first, then
|
|
overwrites security-critical keys:
|
|
|
|
- `OPENSHELL_ENDPOINT`
|
|
- `OPENSHELL_SANDBOX_ID`
|
|
- `OPENSHELL_SANDBOX`
|
|
- `OPENSHELL_SSH_SOCKET_PATH`
|
|
- `OPENSHELL_SANDBOX_COMMAND`
|
|
- TLS path variables when HTTPS is enabled
|
|
|
|
Do not allow sandbox images or templates to override these values.
|