Sandbox image
The layered Docker image, what Kortix injects, constraints, examples, and snapshot rebuilds.
The sandbox base image. For how a session uses it at runtime, see Session runtime.
Every session boots inside a Docker container, built in two parts: your Dockerfile defines the environment (languages, tools, system packages), and the Kortix runtime layer is auto-injected on top so the dashboard can connect.
┌─────────────────────────────────────────┐
│ Kortix runtime layer (auto-injected) │ ← opencode + kortix-agent + ENTRYPOINT
├─────────────────────────────────────────┤
│ Your Dockerfile │ ← .kortix/Dockerfile
└─────────────────────────────────────────┘Referenced from kortix.toml as a named template under [[sandbox.templates]]:
[[sandbox.templates]]
slug = "dev" # any slug except the reserved "default"
name = "Dev box" # optional label
dockerfile = ".kortix/Dockerfile" # OR image = "python:3.12-slim"
cpu = 2 # optional — vCPU cores
memory = 4 # optional — GiB
disk = 20 # optional — GiB
# Make a template the project-wide default so every session (UI, triggers,
# channels) boots it without passing a slug. Omit → the platform default.
[sandbox]
default = "dev"Each entry sets exactly one of dockerfile or image. Paths must be repo-relative — absolute paths and .. traversal are rejected. The singular [sandbox] table with image/build keys on it directly is legacy and rejected; image definitions live under [[sandbox.templates]], and [sandbox] itself only carries default. Field details: kortix.toml.
What the Kortix layer injects
On top of your Dockerfile's final stage, the snapshot builder appends:
USER root(the layer needs to install things).apt-get install -y ca-certificates curl git gzip nodejs npm unzip tmux.npm install -g opencode-ai@<pinned-version>, plus thebunruntime andagent-browser(for the headless-browser tool).- A baked OpenCode tool-dependency cache under
/opt/kortix/(so the boot-timebun installin your config dir is a no-op, not a network round-trip). COPYthekortix-agentdaemon, thekortixCLI, and thekortix-entrypointscript to/usr/local/bin/, plus theagent-cliandexecutor-sdkpackage trees under/opt/kortix/.ENV KORTIX_WORKSPACE=/workspace,WORKDIR /workspace,EXPOSE 8000.ENTRYPOINT ["/usr/local/bin/kortix-entrypoint"].
Everything you installed stays on PATH; the layer relocates and removes nothing.
Constraints
These rules keep a sandbox connectable. They aren't enforced statically — your build succeeds even if you violate them — but the session won't behave correctly.
| Rule | Why |
|---|---|
Don't set ENTRYPOINT. | Kortix overrides it. Your CMD is also ignored. |
Don't claim port 8000. | Reserved for the daemon's reverse proxy. Run your dev servers on other ports. |
FROM a Debian/Ubuntu-family base. | The layer assumes apt-get. Alpine, Fedora, Arch will fail at layer build. |
Don't RUN apt-get clean without rm -rf /var/lib/apt/lists/*. | The Kortix layer re-runs apt-get update; a broken lists cache breaks it. |
| Don't bake credentials into the image. | Use [env] + Secrets Manager — values are injected at session start. |
Everything else is fair game: RUN curl … | sh for toolchains, COPY seed data, set ENV for non-secret config, install any apt/npm packages.
Examples
The starter ships a minimal Ubuntu base:
# syntax=docker/dockerfile:1.7
FROM ubuntu:24.04
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates curl git build-essential \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /workspaceA heavier example with Python + Bun:
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates curl git python3.12 python3.12-venv unzip \
&& rm -rf /var/lib/apt/lists/* \
&& curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:${PATH}"
WORKDIR /workspaceHardware spec
cpu, memory, and disk on a [[sandbox.templates]] entry size the box your sessions run on. All three are optional; an omitted field takes the runtime provider's default. cpu is vCPU cores, memory and disk are GiB. GPUs are not supported in this version — a gpu key is rejected by the manifest validator.
[[sandbox.templates]]
slug = "big"
image = "ubuntu:24.04"
cpu = 4
memory = 8
disk = 50The spec is baked into the snapshot, not set per-session: the provider builds each sandbox from your project's snapshot and inherits its size from there. That has one practical consequence — changing the spec rebuilds the snapshot (it's part of the content hash, below) and the new size applies on the next session, exactly like a Dockerfile edit. Values are rounded to whole numbers; a non-positive value falls back to the default, and anything above the platform ceiling (cpu 32, memory 128 GiB, disk 500 GiB) is clamped down. See kortix.toml → [sandbox] for the full field table and aliases.
Snapshot rebuilds
Snapshots are content-addressed: the platform hashes your Dockerfile + the git tree OID of the build context + the hardware spec + a platform runtime fingerprint (opencode version + kortix-agent binary). Unchanged hash reuses the snapshot; otherwise a new one builds. Rebuilds happen on any push touching your Dockerfile or anything COPY'd into it, or any change to the [sandbox] spec — pure code commits reuse the snapshot for free.
Builds run Daytona-side via Image.fromDockerfile. The first session on a new content hash triggers an inline build (a few minutes, shown as "preparing image"); later sessions on the same content hit the cache.
Editing the Dockerfile inside a session takes effect on the next session; current ones keep their booted snapshot. The edit reaches main only once a change request merges it.