Templates
Pre-baked rootfs images used to boot sandboxes — from a universal apps runtime to a 4 GB browser-automation stack.
A template is a snapshot-ready root filesystem with a pinned kernel. When you Sandbox.create({ template: "..." }), the scheduler restores a snapshot of that template into a fresh microVM — that's how cold-start lands at ~49 ms instead of "boot a kernel from scratch".
Templates are immutable and content-addressed: once a snapshot exists for code-interpreter@v3, every sandbox boots from the same bytes.
Official catalog
PandaStack ships 5 production templates. All names are stable and accepted by template: in the SDKs and --template in the CLI.
CPU and memory are baked into each template at build time — they are a property of the snapshot, not a per-launch knob. Pick a template that matches the size you want, or bake your own with --cpu and --memory-mb.
| Template | Base | vCPU | Memory | Size | What's inside |
|---|---|---|---|---|---|
base | Ubuntu 24.04 + mise | 2 | 2 GB | 2 GB | Universal apps runtime — Node 22, Python 3.12, Go, Bun via mise. The default for apps & general use. |
code-interpreter | Python 3.11 + Node 22 | 2 | 2 GB | 2 GB | pandas, numpy, matplotlib, scipy, scikit-learn, jupyter, playwright, openai-agents. LLM tool-use, data analysis, Functions, agents. |
agent | Ubuntu 24.04 + Node 22 | 2 | 2 GB | 2 GB | Every public coding-agent CLI in one image: claude-code, codex, opencode. Pick one via its API key. |
browser | Ubuntu 24.04 + Chromium | 4 | 4 GB | 4 GB | Headless Chromium + Playwright + crawl4ai. Scraping, RPA, screenshots, LLM-friendly web extraction. |
postgres-16 | Ubuntu 24.04 + PGDG | 2 | 1 GB | 2 GB | Managed PostgreSQL 16 + pgvector + pgbouncer on a durable volume. |
Every template autostarts sshd and the pandastack-agent systemd unit. When you deploy an app on the base runtime, its dev/start command runs via pandastack-autostart.service, so the preview URL works the instant the sandbox is running.
Older SDKs accepted cpu and memory_mb arguments on Sandbox.create(...). Those arguments are now deprecated and ignored — the server always uses the template's baked size. Pass them and you'll get a deprecation warning; the sandbox will still launch at the template's size. To run at a different size, bake a new template.
Picking a template
| If you're doing… | Use… |
|---|---|
| Running apps — Node / Python / Go / Bun | base |
| LLM tool calling, data analysis, Jupyter-style | code-interpreter |
| Running Claude Code / Codex / OpenCode as an agent | agent |
| Browser automation, scraping, screenshots, crawling | browser |
| Managed PostgreSQL 16 with pgvector | postgres-16 |
| Anything custom | bake your own (below) |
Bake your own
A custom template is just a Dockerfile plus a CPU/memory spec and a size limit. You give PandaStack a Dockerfile and it does the rest — builds the image, flattens it to a rootfs, and bakes a snapshot. You need only an API key: no local Docker, no registry credentials. The request is the Dockerfile plus an optional small build context (≤50 MB), never a multi-GB rootfs, so there is no upload-size cliff.
Debian-based images only. Your base image must be Debian or a Debian derivative — debian, ubuntu, python, node, etc. Alpine, RedHat-based (Fedora/CentOS/Rocky/Alma/UBI), distroless, and other non-Debian distributions are not supported (the microVM's init + SSH contract needs apt/glibc). A non-Debian FROM is rejected before the build starts.
One command: template build
Start from any Dockerfile (e.g. fork templates/base/Dockerfile), then:
pandastack template build \
--name my-template \
-f Dockerfile \
--context . # include files your Dockerfile COPYs (entrypoint.sh, app/, …)
--cpu 4 \
--memory-mb 4096 \
--size-mb 2048If your Dockerfile uses COPY/ADD, pass --context <dir> so those files are uploaded with it — otherwise the build fails with COPY failed: file not found in build context. The context is capped at 50 MB / 50 files (it's the source, not the built rootfs).
This uploads the Dockerfile, kicks off a server-side build, and streams the build logs live until the snapshot is ready. --cpu and --memory-mb are baked into the snapshot and become the size of every sandbox launched from this template. Add --context ./dir to include files your Dockerfile COPYs.
The SDKs expose the same flow:
from pandastack import Client
client = Client()
build = client.templates.build_from_dockerfile(
"my-template",
"Dockerfile", # path on disk, or inline Dockerfile content
context_dir="./app", # optional — files for COPY/ADD
cpu=4, memory_mb=4096, size_mb=2048,
)
for line in client.templates.build_logs(build.id): # live logs
print(line)
final = client.templates.wait_for_build(build.id) # raises TemplateBuildError on failureconst build = await client.templates.buildFromDockerfile({
name: "my-template",
dockerfile: "FROM ubuntu:24.04\nRUN apt-get update && apt-get install -y curl\n",
cpu: 4, memoryMb: 4096, sizeMb: 2048,
});
for await (const line of client.templates.buildLogs(build.id)) {
console.log(line); // live build logs until the build finishes
}The build pipeline (all server-side):
- Your Dockerfile + context are staged and built with Google Cloud Build (with Docker layer caching — see below), and the image is pushed to PandaStack's private registry.
- An agent pulls the image and flattens its layers into a rootfs (whiteouts resolved — equivalent to
docker export), writes a sparse ext4 ofsize_mbMB, and injects working guest DNS. - Publishes a durable copy to object storage (so any host can serve later launches).
- Boots the image once under Firecracker and takes a memory + disk snapshot.
- Marks the build
done—my-templateis instantly available forSandbox.create.
Advanced — bring your own image. If you already build + push images yourself (e.g. in your own CI), skip the Dockerfile upload and register by reference: client.templates.register({ name, imageRef }), or the pandastack template push CLI command (which runs a local docker build + docker push then registers). This needs Docker + registry access on your side.
Example Dockerfiles
Add a few system packages to the universal runtime. The simplest custom template — start from ubuntu and apt install what you need:
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
ffmpeg imagemagick poppler-utils \
&& rm -rf /var/lib/apt/lists/*pandastack template build --name media-tools -f Dockerfile --size-mb 2048Pin a specific language runtime + dependencies. Bake your dependencies in so every sandbox starts ready — no install step at create time:
FROM python:3.12-slim
RUN pip install --no-cache-dir \
pandas numpy scikit-learn duckdb pyarrow
# Bake your own code/assets too:
COPY ./pipeline /opt/pipelinepandastack template build --name data-pipeline -f Dockerfile --context . --size-mb 3072A heavier toolchain image. Multi-runtime images are fine — just keep the final stage Debian-based (earlier build stages can be anything):
# Build stage may use any base…
FROM golang:1.22 AS build
WORKDIR /src
COPY . .
RUN go build -o /out/app ./cmd/app
# …but the FINAL stage must be Debian-derived.
FROM debian:12-slim
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY --from=build /out/app /usr/local/bin/appSizing tip: --size-mb is the ext4 rootfs size — make it comfortably larger than your image's unpacked size (e.g. a 1.5 GB image → --size-mb 3072) so there's headroom for runtime writes. --cpu/--memory-mb are the VM size baked into the snapshot; every sandbox from this template gets exactly that.
Notes & requirements
- Debian base only —
debian,ubuntu,python,node,golang, etc. See the callout at the top of this section; non-DebianFROMis rejected before the build runs. sshd+ an init are auto-handled. Booting as a microVM needs an init (/sbin/init) andsshd(the host↔guest exec bridge). If your image lacks them — most application images likepython:3.12-slimornode:20-slimdo — the build automatically installssystemd-sysv+openssh-serverinto the rootfs and injects an SSH key. You don't add them to your Dockerfile or set a special entrypoint; just build a normal image. (ACMD/ENTRYPOINTyou set isn't the VM's init and isn't used for boot.)- Size is fixed per template.
cpu/memory_mbare baked into the snapshot. To change them, build a new template — they can't be overridden onSandbox.create. - Source caps: Dockerfile ≤ 512 KB, build context ≤ 50 MB across ≤ 50 files. This is the source you upload, not the built rootfs — large images are fine, you just can't ship 50 MB+ of context files inline. For big assets,
RUN curl/git clonethem during the build instead ofCOPYing. - Builds run
linux/amd64. Don't rely on arch-specificFROMtags. - Naming:
[a-zA-Z0-9._-], ≤ 64 chars. Re-runningtemplate buildwith the same name replaces it (and reuses cached layers).
Troubleshooting
| Error | Cause & fix |
|---|---|
COPY failed: file not found in build context | Your Dockerfile COPYs a file you didn't upload. Pass --context <dir> (often --context .). |
unsupported base image … only Debian-based images are supported | A non-Debian FROM (Alpine, Fedora, distroless, …). Switch to a Debian/Ubuntu base. |
build context too large / too many build-context files | Context exceeds 50 MB / 50 files. Fetch large assets during the build (RUN curl …) instead of COPYing them. |
Build stuck on a slow RUN (compiling from source) | Heavy builds run on an 8-vCPU builder, but compiling multiple language runtimes from source is still minutes-long. Prefer prebuilt runtime base images (python:3.12, node:20) over pyenv/rbenv-from-source where you can. |
template build failed with no obvious step | Stream the full log: pandastack template build-logs <id> — the failing Step N/NN and its output are there. |
Caching
Rebuilds are fast and cheap:
- Content dedup — an identical Dockerfile + context + size spec short-circuits to the existing template; no rebuild runs at all.
- Docker layer cache — a changed Dockerfile reuses unchanged layers from the previous build (
--cache-from). - Snapshot reuse — every
Sandbox.createrestores the one baked snapshot; the image is never rebuilt per launch.
Streaming build logs
Every build emits timestamped progress (pulling, mounting + extracting, installing, baking, …). Stream them any time:
pandastack template build-logs <build_id> --followfor line in client.templates.build_logs(build_id, follow=True):
print(line)Or just wait for the terminal result:
final = client.templates.wait_for_build(build_id) # raises TemplateBuildError on failureA typical 2 GB template takes 1–2 min end to end (Cloud Build + snapshot bake); a 4 GB one takes 3–5 min. Cached rebuilds are much faster.
Versioning and pinning
template: "code-interpreter" resolves to the latest snapshot tagged code-interpreter. To pin, pass the snapshot ID directly:
await Sandbox.create({ fromSnapshot: "snap-019fe18f-…" });Useful for reproducibility: tie a release of your agent to a known template snapshot, regardless of what the cloud rolls out later.
CLI
pandastack template list
pandastack template get code-interpreter
pandastack template build -f Dockerfile --name my-template --size-mb 2048 # server-side build (recommended)
pandastack template build-logs <id> --follow # stream a build's progress
pandastack template build-status <id> # poll a single build
pandastack template builds # all recent build jobs
pandastack template push -f Dockerfile --name my-template # (advanced) local docker build + push
pandastack template delete my-template
pandastack sandbox create --template code-interpreter --ttl 1hREST equivalents
GET /v1/templates
GET /v1/templates/{name}
POST /v1/templates/build (name, size_mb, cpu, memory_mb; plus ONE of: dockerfile (+context files, server-side build), image_ref (pre-built image), or a rootfs file)
GET /v1/templates/builds
GET /v1/templates/builds/{id}
GET /v1/templates/builds/{id}/logs (SSE; ?follow=1 to tail live)
DELETE /v1/templates/{name} (also clears the cached snapshot)The image_ref form field is the registry path (recommended); the legacy rootfs tarball field still works for small templates and local development.
Branch & Explore
Best-of-N over sub-second copy-on-write forks — try N approaches in parallel real execution and keep the winner. Tree-of-thought for agents, over the world instead of over tokens.
Hosted MCP Server
A workspace-level MCP endpoint at api.pandastack.ai/mcp — connect Claude, Cursor, or any MCP client once and manage sandboxes, databases, and apps with 13 tools.