Skip to content

Any OCI Image

Pass any OCI image reference to the Sandbox() constructor and isorun will pull it on first use, build a golden snapshot, and reuse that snapshot for every subsequent boot of the same image. The golden snapshot creation is one-time per (image, runner) pair — after that, every sb.create() of that image hits the standard ~27 ms cold-start path.

Examples

from isorun import Sandbox
# Standard library images — no separate setup needed
Sandbox("python:3.12")
Sandbox("node:22")
Sandbox("ubuntu:24.04")
Sandbox("alpine:3.20")
Sandbox("ruby:3.3")
Sandbox("golang:1.23")
Sandbox("rust:1.83")
# Specialized agent images
Sandbox("python:3.12-slim")
Sandbox("mcr.microsoft.com/playwright/python:v1.48.0")
Sandbox("jupyter/scipy-notebook:latest")
# Your own image (build + push, then reference by ref)
Sandbox("ghcr.io/your-org/agent-runtime:1.0")
Sandbox("docker.io/youraccount/data-pipeline:v3")
# Private registries — same syntax, just authenticate the runner
Sandbox("registry.internal.example.com/team/agent:latest")

How it works

  1. The first time the runner sees an image reference, it pulls the image via crane (parallel layer downloads).
  2. Layers are extracted into an EROFS read-only rootfs.
  3. The runner injects the isorun guest agent + busybox + an init script that boots the agent before the user’s command.
  4. The runner boots the EROFS image once inside Firecracker, runs the canonical pre-warm command for the image’s interpreter (node -v, python3 -V, etc.), then snapshots the running VM.
  5. The snapshot becomes the golden image for that ref. Subsequent sb.create() calls hardlink the snapshot’s mem.snap into a per-VM run dir and restore in ~27 ms.

The first build takes 10-60 seconds depending on image size and network. Every boot after that is the standard cold-start.

Reject ambiguous tags

latest, lts, and stable tags are rejected at create time — they change without notice and would silently invalidate your golden snapshot when the upstream tag is republished. Use a pinned tag (python:3.12, node:22-slim) or a digest reference (python@sha256:...).

Image build endpoint

If you want to pre-build an image’s golden snapshot ahead of time (for example, in CI before a launch), the runner exposes a build endpoint:

Terminal window
curl -X POST https://api.isorun.ai/v1/images/build \
-H "Authorization: Bearer $ISORUN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"image": "your-image:1.0"}'

This is the same code path that runs lazily on first sb.create() — calling it ahead of time just amortizes the cost outside the critical path of the first user request.

Custom image content

Inside the sandbox, the rootfs is overlay-mounted with a writable scratch disk on top of the read-only EROFS. Anything the user code writes to /, /tmp, /home, etc. ends up on the scratch disk and is preserved for the sandbox’s lifetime (and across hibernate / resume cycles, if you use those).

The original image’s ENTRYPOINT and CMD are not run by the runner — the init script replaces them with the isorun guest agent. If your image has a startup hook (e.g. a daemon that needs to launch on boot), wrap it in a script and call it explicitly with sb.exec("/usr/local/bin/start-services.sh &") after sb.create().

The OCI image’s environment variables (PATH, NODE_VERSION, etc.) are applied — the runner reads the image config at build time and injects them via the agent’s set_env message during boot.