Prebuilt sandbox snapshots: build once, create sandboxes instantly.
Building a sandbox from an ExDaytona.Image runs the Docker build on
every create. The fast production pattern is to build a snapshot
from the image once and create every sandbox from it:
image =
ExDaytona.Image.from("ubuntu:22.04")
|> ExDaytona.Image.run("apt-get update && apt-get install -y curl git")
{:ok, snapshot} =
ExDaytona.Snapshot.build(client, "my-app-base", image, log: &IO.write/1)
# From here on, creation skips the build entirely:
{:ok, sandbox} = ExDaytona.Sandbox.create(client, snapshot: "my-app-base")Snapshots can also wrap a registry image (image_name:) instead of a
declarative build, and can be deactivated/reactivated to manage the
organization's snapshot quota (ExDaytona.Quota.overview/2 reports
usage). For pre-warmed running sandboxes on top of a snapshot, see
ExDaytona.WarmPool.
Summary
Functions
Reactivate a deactivated snapshot. Returns the updated
ExDaytona.Model.SnapshotDto.
Poll until the snapshot reaches state (a string or list of strings,
e.g. "active").
Build a snapshot from an image and wait for it to become active —
create/3 with the image required and optional live build-log
streaming
The snapshot's build logs so far, as a binary. Only snapshots created from build info have build logs.
Create a snapshot named name and (by default) wait for it to become
active.
Deactivate a snapshot (it stops counting toward active usage; sandboxes
can no longer be created from it until reactivated). Returns :ok.
Delete a snapshot by id. Returns :ok.
Fetch a snapshot by id or name as an ExDaytona.Model.SnapshotDto.
List snapshots. Accepts :page, :limit, :name (partial match),
:source_sandbox_id, :sort, :order; returns
{:ok, %{items: [%ExDaytona.Model.SnapshotDto{}], page: n, total: n, total_pages: n}}.
Follow the snapshot's build logs in real time: fun is invoked with
each chunk as it is produced, and the call returns :ok when the build
finishes and the stream closes.
Functions
@spec activate(ExDaytona.Client.t(), String.t()) :: {:ok, ExDaytona.Model.SnapshotDto.t()} | {:error, ExDaytona.Error.t()}
Reactivate a deactivated snapshot. Returns the updated
ExDaytona.Model.SnapshotDto.
@spec await_state( ExDaytona.Client.t(), String.t(), String.t() | [String.t()], keyword() ) :: {:ok, ExDaytona.Model.SnapshotDto.t()} | {:error, ExDaytona.Error.t()}
Poll until the snapshot reaches state (a string or list of strings,
e.g. "active").
Fails fast with {:error, %Error{}} when the snapshot enters an error
state (["error", "build_failed"], with the provider's errorReason
in the message), and with a timeout error after :timeout milliseconds
(default 300_000; poll interval :poll_interval, default 2_000).
@spec build( ExDaytona.Client.t(), String.t(), ExDaytona.Image.t() | String.t(), keyword() ) :: {:ok, ExDaytona.Model.SnapshotDto.t()} | {:error, ExDaytona.Error.t()}
Build a snapshot from an image and wait for it to become active —
create/3 with the image required and optional live build-log
streaming:
{:ok, snapshot} =
ExDaytona.Snapshot.build(client, "my-app-base", image,
log: &IO.write/1,
timeout: 600_000
)Options
:log— a fun invoked with each build-log chunk while the build runs (streamed concurrently viastream_build_logs/4)- everything
create/3accepts except:image/:wait(build always waits — a snapshot is only usefulactive)
@spec build_logs(ExDaytona.Client.t(), String.t()) :: {:ok, binary()} | {:error, ExDaytona.Error.t()}
The snapshot's build logs so far, as a binary. Only snapshots created from build info have build logs.
@spec create(ExDaytona.Client.t(), String.t(), keyword()) :: {:ok, ExDaytona.Model.SnapshotDto.t()} | {:error, ExDaytona.Error.t()}
Create a snapshot named name and (by default) wait for it to become
active.
Options
:image— build declaratively: anExDaytona.Imageor a raw Dockerfile string (local build contexts are uploaded automatically, as inExDaytona.Sandbox.create/2):image_name— wrap an existing registry image instead of building:wait— wait until the snapshot isactive(defaulttrue):timeout— max milliseconds to wait (default300_000— builds take longer than sandbox starts):poll_interval— milliseconds between state polls (default2_000)- snapshot settings, all optional:
:entrypoint(list),:cpu,:memory,:disk,:gpu,:gpu_type,:region_id,:sandbox_class
Returns {:ok, %ExDaytona.Model.SnapshotDto{}}. Watch a build in
progress with stream_build_logs/4, or use build/4 to do both in
one call.
@spec deactivate(ExDaytona.Client.t(), String.t()) :: :ok | {:error, ExDaytona.Error.t()}
Deactivate a snapshot (it stops counting toward active usage; sandboxes
can no longer be created from it until reactivated). Returns :ok.
@spec delete(ExDaytona.Client.t(), String.t()) :: :ok | {:error, ExDaytona.Error.t()}
Delete a snapshot by id. Returns :ok.
@spec get(ExDaytona.Client.t(), String.t()) :: {:ok, ExDaytona.Model.SnapshotDto.t()} | {:error, ExDaytona.Error.t()}
Fetch a snapshot by id or name as an ExDaytona.Model.SnapshotDto.
@spec list( ExDaytona.Client.t(), keyword() ) :: {:ok, %{ items: [ExDaytona.Model.SnapshotDto.t()], page: number() | nil, total: number() | nil, total_pages: number() | nil }} | {:error, ExDaytona.Error.t()}
List snapshots. Accepts :page, :limit, :name (partial match),
:source_sandbox_id, :sort, :order; returns
{:ok, %{items: [%ExDaytona.Model.SnapshotDto{}], page: n, total: n, total_pages: n}}.
@spec stream_build_logs( ExDaytona.Client.t(), String.t(), (binary() -> any()), keyword() ) :: :ok | {:error, ExDaytona.Error.t()}
Follow the snapshot's build logs in real time: fun is invoked with
each chunk as it is produced, and the call returns :ok when the build
finishes and the stream closes.
Options: :timeout — max milliseconds to wait between chunks
(default :infinity); :deadline — overall milliseconds for the
stream.