* feat(sandbox): use policy-first OCI image identity Closes #2331 Preserve per-field policy omission, derive Docker and Podman fallbacks from the inspected immutable image, and resolve the final numeric identity before starting agent children. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * fix(sandbox): preserve declared process identities Keep explicit policy values and OCI-declared names intact, defer passwd lookup until a primary GID is required, and refresh stale policy examples. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * fix(supervisor): reuse resolved OCI identity Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * fix(supervisor): allow Linux pre-exec arguments Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * fix(kubernetes): protect resolved sandbox identity Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * fix(sandbox): prepare workspace for OCI identity Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * refactor(sandbox): own only workspace root Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * fix(sandbox): harden partial identity drops Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * test(sandbox): scope OCI image e2e to Docker Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * fix(sandbox): narrow OCI identity fallback scope Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * test(podman): cover OCI identity launch Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * fix(podman): exercise OCI fallback in E2E Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> --------- Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
Bring Your Own Container
Run a sandbox with a custom container image. This example includes a ready-to-use Python REST API that you can build, deploy, and reach from your local machine through port forwarding.
Prerequisites
- A running OpenShell gateway (
mise run gateway:dockerfor local development) - Docker daemon running
What's in this example
| File | Description |
|---|---|
Dockerfile |
Builds a Python 3.12 image that starts a REST API |
app.py |
Minimal HTTP server with /hello and /health routes |
Quick start
1. Create a sandbox from the Dockerfile with port forwarding
openshell sandbox create \
--from examples/bring-your-own-container/Dockerfile \
--forward 8080 \
-- python /sandbox/app.py
The --from flag accepts a Dockerfile path. The CLI builds the image,
pushes it into the cluster, and creates the sandbox in one step.
The --forward 8080 flag opens an SSH tunnel so localhost:8080 on your
machine reaches the REST API inside the sandbox.
Important: The image's CMD / ENTRYPOINT does not run automatically.
OpenShell replaces it with the sandbox supervisor (which manages SSH access,
network policy, etc.). You must pass your application's start command
after -- so it is executed via SSH once the sandbox is ready.
2. Hit the API
curl http://localhost:8080/hello
# {"message": "hello from OpenShell sandbox!"}
curl http://localhost:8080/hello/world
# {"message": "hello, world!"}
curl http://localhost:8080/health
# {"status": "ok"}
Running your own app
Replace app.py and the Dockerfile with your own application. The
key requirements are:
- Pass your start command explicitly — use
-- <command>on the CLI. The image'sCMD/ENTRYPOINTis replaced by the sandbox supervisor at runtime. - Declare a non-root OCI
USERfor Docker and Podman. Use a named account such asapp, a numeric UID with a passwd entry that supplies its primary GID, or a numeric pair such as1500:1500. You can instead set bothprocess.run_as_userandprocess.run_as_groupexplicitly in policy. - Prepare
/sandboxas the workspace. Until OCI working-directory support is added, create/sandboxand make it writable by the selected identity. The example does this withinstall -d -o app -g app /sandbox. - Install
iproute2for full network namespace isolation. - Use a standard Linux base image — distroless and
FROM scratchimages are not supported.
How it works
OpenShell handles all the wiring automatically. You build a standard
Linux container image — no OpenShell-specific dependencies or
configuration required. When you create a sandbox with --from,
OpenShell ensures that sandboxing (network policy, filesystem isolation,
SSH access) works the same as with the default image.
Port forwarding is entirely client-side: the CLI spawns a background
ssh -L tunnel through the gateway. The sandbox's embedded SSH daemon
bridges the tunnel to 127.0.0.1:<port> inside the container.
Cleanup
Delete the sandbox when you're done (this also stops port forwards):
openshell sandbox delete <sandbox-name>