Skip to content

Images

View as Markdown

An image is the filesystem a sandbox boots from, together with the environment variables, working directory, entrypoint, and command the sandbox starts with. Daytona accepts standard OCI images, the same ones you build and push with Docker, and converts each one into a boot-optimized format when you register it. Images belong to a project, and a sandbox references its image by name or ID. A sandbox create does not pull from a registry, so a sandbox boots only from an image already registered in the project.

Every sandbox created from an image starts with the same filesystem and configuration. An image holds no running processes or memory. A snapshot saves the memory and disk of a running sandbox, and a restored sandbox resumes its processes.

ConceptDescription
Registry imageAn image pulled from a public or private registry and registered under a name.
Dockerfile buildAn image Daytona builds from Dockerfile text, with or without a build context.
CaptureAn image made from the filesystem of a running Linux sandbox.
Anonymous imageAn image without a name. Daytona deletes it after it goes unused for its idle window.
Statuspending, building, ready, or failed. Sandboxes boot only from a ready image.
Home regionThe region where Daytona builds, pulls, or captures the image.

Images are used when many sandboxes need the same software, files, or configuration.

  • Preinstalled dependencies: packages, language runtimes, and tools are installed once in a Dockerfile build, and every sandbox from the image starts with them.
  • Shared environments: a named image gives every sandbox in a project the same filesystem and start configuration under one name.
  • Pinned environments: a registry image is registered under a name, so a moved or deleted registry tag does not change what sandboxes boot.
  • Configured sandboxes as templates: a sandbox set up by hand or by an agent is captured, and new sandboxes start from its filesystem.
  • Private application images: images that a CI pipeline pushes to a private registry are imported with the project’s registry credentials and boot in sandboxes.
  • Environments written by agents: an agent writes a Dockerfile, builds it, and boots sandboxes from the result, without access to your build infrastructure.
  • amd64 and arm64 builds: one Dockerfile builds for either CPU architecture, so sandboxes on both kinds of host run the same software.
  • Evaluation and reinforcement learning (RL): each test case or episode starts in a new sandbox from the same image, so results do not depend on another run.

Create a sandbox from an image registered in the project, by its name or ID. A sandbox create does not pull from a registry, so the image is pulled, built, or captured first. Registration runs in the background, and a create from an image that is not ready yet fails.

from daytona import Daytona
daytona = Daytona()
# Register python:3.12-slim under the name python-3.12
image = daytona.v2.images.pull("python:3.12-slim", name="python-3.12")
# Each wait returns after 30 seconds at most; a create from an image that is not ready fails
while image.status not in ("ready", "failed"):
image = daytona.v2.images.get(image.id, wait="ready")
if image.status == "failed":
raise RuntimeError(image.error)
sandbox = daytona.v2.create("python-3.12")
  • images.get(id, wait="ready") returns when the image is ready or failed, or when the server wait expires.
  • Set timeout in seconds to change the server wait, up to 60.
  • images.get() does not raise on failed or on expiry, so check status and error on the returned image.
  • A value that contains / or : is treated as a registry reference.

Build an image from Dockerfile text and create a sandbox from it. The SDKs do both in one call. The image is anonymous: it has no name, and the default image list does not show it. Daytona deletes an anonymous image once it goes unused for its idle window, the server maximum of 7 days by default; every sandbox create from the image restarts the window.

The Dockerfile must be self-contained. There is no build context, so instructions that copy local files have nothing to copy. Use a build context for those.

from daytona import Daytona
from daytona.v2 import ImageBuilder
daytona = Daytona()
# Builds an anonymous image from the Dockerfile, then creates the sandbox from it
sandbox = daytona.v2.create_from_build(
ImageBuilder.from_dockerfile("FROM python:3.12-slim\nRUN pip install requests\n")
)
ParameterTypeDescription
waitintSets one time budget in seconds for the build and the create together. A build that runs longer fails with 408 REQUEST_TIMEOUT. Raise the value for longer builds, or pass 0 to remove the limit. The default is 60.
idleintSets the idle window of the image in seconds. It applies only to the image.
regionstrSelects the region for both the build and the sandbox.
  • cpu_arch also applies to both the build and the sandbox.
  • Every other keyword goes to create.
  • A failed build creates no sandbox.

Pull an image from a registry and register it under a name. The pull runs in the background, and the call returns once it is queued. Pulling again under the name of an existing registry or Dockerfile image re-imports the image: it returns to pending, and sandbox creates from it fail until the new pull is ready. A private registry authenticates with the registry credential stored for the image host.

from daytona import Daytona
daytona = Daytona()
image = daytona.v2.images.pull("ghcr.io/acme/agent:v3", name="my-awesome-image")
ParameterTypeDescription
namestrSets the image name. The name is 1 to 128 characters of letters, digits, ., _, and -. It must not start with ., snap-, build-, refs, by-digest, or prj-. It must not look like an image ID, img_.... Images and snapshots share one name space per project. A name that belongs to a captured image or a snapshot returns 409. Without a name, the image is anonymous. An anonymous pull reuses an existing pending, building, or ready anonymous image of the same reference in the same region.
  • Wait with images.get(image.id, wait="ready") before creating sandboxes.

Build an image from a Dockerfile and register it under a name. The build runs in the background: the call returns once it is queued, and the image can be used once it is ready.

Builds are deduplicated within a project and region. Submitting the same Dockerfile and build context for the same CPU architecture reuses the earlier build instead of running a new one; if that build already finished, the new image is ready at once.

from daytona import Daytona
from daytona.v2 import ImageBuilder
daytona = Daytona()
image = daytona.v2.images.build(
ImageBuilder.from_dockerfile("FROM python:3.12-slim\nRUN pip install requests"),
name="my-awesome-image",
)
ParameterTypeDescription
namestrSets the image name. Without a name, the image is anonymous.
idleintSets how many seconds an anonymous image can go without a sandbox create before deletion. It applies only to anonymous images. -1 sets the maximum. The default is the server maximum.
  • images.build takes an ImageBuilder, not a raw Dockerfile string.
  • Wait with images.get(image.id, wait="ready") before use.

Build an image from a Dockerfile and a build context. Daytona uploads the context with the request and runs the build in the image’s home region. A build context is needed when the Dockerfile copies local files. Without one, the Dockerfile is sent as text, as in build images.

Terminal window
# The context holds the Dockerfile at its root
daytona image build my-awesome-image --context context.tar
FlagTypeDescription
--contextstringSets the build context, a tar archive or a directory. The packed context is at most 64 MiB. This flag is required.
--dockerfilestringSets the path of the Dockerfile inside the context. The default is Dockerfile.
--timeoutstringSets how long the command waits for the build to finish. The default is 10m.
--no-waitbooleanReturns once the build is queued, without waiting for it to finish.
  • The command exits with an error if the build fails.

Build accepts an optional home region and CPU architecture. Pull accepts only a home region and always uses the region’s architecture. The same Dockerfile built for two architectures produces two separate images.

from daytona import Daytona
from daytona.v2 import ImageBuilder
daytona = Daytona()
image = daytona.v2.images.build(
ImageBuilder.from_dockerfile("FROM python:3.12-slim\nRUN pip install requests"),
name="my-awesome-image",
region="us",
cpu_arch="arm64",
)
ParameterTypeDescription
regionstrSets the home region of the image. The default is the resolved default region for the project, organization, or platform.
cpu_archstrSets the CPU architecture to build for, amd64 or arm64. The pull methods accept only region, not cpu_arch. A from_registry builder with no steps is also a pull, so cpu_arch does not apply to that builder either. The default is the region’s architecture.

Describe an image in code instead of writing a Dockerfile. Start from a registry image, chain the steps the image needs, and build it like any other image. Each step adds one Dockerfile instruction, and the SDK renders the Dockerfile when the build is submitted.

Both SDKs render the same Dockerfile for the same steps, so a build submitted from Python and the same build submitted from TypeScript are deduplicated into one image. A sandbox booted from the image gets its environment variables and runs its entrypoint and command in its working directory, or in the user’s home directory when the image sets none or sets the root directory. The image’s user does not carry over: sandboxes run as root unless a user is set when the sandbox is created.

from daytona import Daytona
from daytona.v2 import ImageBuilder
daytona = Daytona()
builder = (
ImageBuilder.from_registry("python:3.12-slim")
.pip_install("requests", "numpy>=1.26")
.run_commands("mkdir -p /app/data")
.env({"LOG_LEVEL": "debug"})
.workdir("/app")
)
image = daytona.v2.images.build(builder, name="my-awesome-image")
MethodTypeDescription
from_registrystrSets the registry image reference to start from, rendered as FROM. A builder from from_registry with no steps is a registry import, not a build. images.build pulls that image as pull images does. from_dockerfile starts from Dockerfile text instead, and the steps are appended after that text. This method is required unless the builder starts from from_dockerfile.
pip_install*strAdds Python packages as one RUN python -m pip install step. Each package is shell-quoted, so a version specifier such as numpy>=1.26 stays one argument.
run_commands*strAdds shell commands as one RUN step per command.
envstr, str or Mapping[str, str]Sets one variable as a name and a value, or several as a mapping. Each variable is rendered as one ENV step.
workdirstrSets the working directory, rendered as WORKDIR.
  • Each method returns a new builder and leaves the original unchanged, so one base builder can start several images.

Render the Dockerfile a builder describes and the request body it produces, without submitting a build. Use it to review the generated instructions, or to send the build yourself through the API.

from daytona.v2 import ImageBuilder
builder = ImageBuilder.from_registry("python:3.12-slim").pip_install("requests")
print(builder.render_dockerfile())
# FROM python:3.12-slim
# RUN python -m pip install requests
source, dockerfile = builder.build_request_source()
  • build_request_source returns the two POST /images fields as a tuple, and one of the two is None.
  • For a registry import with no steps, source holds {"type": "registry", "ref": ...}.
  • For any other builder, dockerfile holds the rendered text.

Capture the filesystem of a running sandbox as an image. The sandbox keeps running, and new sandboxes boot from the image. The capture runs in the background: the image starts as pending and becomes ready when the capture finishes. Linux sandboxes can be captured; a macOS sandbox cannot be captured.

A named capture is permanent until you delete it. An unnamed capture is anonymous and is deleted once unused for its idle window, the server maximum of 7 days by default; every sandbox create from the image restarts the window. To keep an anonymous capture, promote it.

from daytona import Daytona
daytona = Daytona()
sandbox = daytona.v2.create("python-3.12")
sandbox.process.run("pip install requests")
image = sandbox.snapshot_filesystem(name="my-env")
# Wait until the capture is ready, then boot new sandboxes from it
while image.status not in ("ready", "failed"):
image = daytona.v2.images.get(image.id, wait="ready")
if image.status == "failed":
raise RuntimeError(image.error)
clone = daytona.v2.create("my-env")
ParameterTypeDescription
namestrSets the image name, which must be unique in the project. The default is None, which makes the image anonymous.
idleintSets how many seconds an anonymous image can go without a sandbox create before deletion. It applies only to anonymous images. -1 sets the maximum. The default is the server maximum.
  • snapshot_filesystem returns the pending Image and does not wait for the capture.

Promote an anonymous image by giving it a name. A promoted image is permanent: it is no longer deleted after its idle window, and the default image list shows it. Promotion works only on anonymous images; an image that already has a name cannot be renamed.

from daytona import Daytona
daytona = Daytona()
image = daytona.v2.images.promote("{imageId}", "my-env")
print(image.name)
ParameterTypeDescription
image_idstrIdentifies the image by its ID, img_.... This parameter is required.
namestrSets the image name, which must be unique in the project. This parameter is required.

Convert an image to the current image format before its first use. Images registered by the migration from Daytona v0 are stored in an older format until they are converted. Such an image converts on its first Linux sandbox create, which waits in the queued state while the conversion runs. Builds that name the image as their source refuse it until it is converted. Converting ahead of time removes the wait from the first create and makes the image usable everywhere.

Terminal window
curl 'https://api.daytona.com/images/{imageId}/convert' \
--request POST \
--header 'Authorization: Bearer YOUR_API_KEY'
# Returns on ready or failed, or after timeout_ms; repeat while status is pending or building
curl 'https://api.daytona.com/images/{imageId}?wait=ready&timeout_ms=60000' \
--header 'Authorization: Bearer YOUR_API_KEY'

The response has the following fields:

FieldDescription
convertedThe value is true when the call started a conversion or joined one in progress. The value is false when the image is already in the current format and nothing was queued.
  • The call takes the image ID, img_....
  • The call returns 202 with id, from_format, to_format, status, and converted.
  • An image that needs conversion has format_outdated set to true.
  • The call is safe to repeat. It joins a conversion in progress and retries a failed one.
  • The call requires the write:images permission.
  • Other sandbox classes and builds refuse an unconverted image with 409 IMAGE_FORMAT_OUTDATED.
  • While the conversion runs, other sandbox classes and builds refuse the image with 409 IMAGE_NOT_READY.
  • POST /images/{imageId}/convert returns 409 when the image records no source it can be converted from.

List images in the project, newest first. The list returns named images by default. Anonymous images, such as the ones inline Dockerfile builds create, appear only when you ask for them.

from daytona import Daytona
daytona = Daytona()
page = daytona.v2.images.list()
for image in page.items:
print(image.name, image.status)
ParameterTypeDescription
anonymousbool | Literal["any"]Selects which images to list. True returns anonymous images only, and "any" returns both named and anonymous images. The default is False.
limitintSets the page size, clamped to 1 through 200. The default is 100.
  • page.next_cursor is set when more images exist.

Each image has the following fields:

FieldDescription
idImage ID (img_...), used by the get, promote, convert, build-logs-url, and delete endpoints; returned as id when the image is created
nameThe name sandboxes reference through image
statuspending, building, ready, or failed
errorBuild failure reason; null unless status is failed
sourceThe build source as submitted: a registry reference, a named image, or a Dockerfile context; null for captured images
regionHome region the image was built or pulled in
available_inRegions that hold a copy of the image right now; the home region is listed only while its own copy is there. Empty until the build finishes and after every copy is evicted
manifest_nameName of the converted image manifest; null until the build completes
bytesSize of the converted image in bytes; null until the build completes
layer_countNumber of layers in the converted image
format_versionStorage format of the image: 1 for images registered by the migration from Daytona v1, 2 for the current format
format_outdatedtrue when format_version is below the current format; convert the image before use outside Linux sandboxes
created_atCreation timestamp
cursorToken to resume the list immediately after this row; returned by list only

Iterate over every image in the project without handling page cursors. The iterator requests the next page when the current page is exhausted.

from daytona import Daytona
daytona = Daytona()
for image in daytona.v2.images.iter():
print(image.name, image.status)

Get an image by its ID. The response carries the image fields described under list images, including its status and failure reason. A name is not accepted; to find an image by name, filter the image list by name.

from daytona import Daytona
daytona = Daytona()
image = daytona.v2.images.get("{imageId}")
print(image.name, image.status)
  • To find an image by name, use images.list(name="NAME").

Delete an image. Deletion fails while a sandbox created from the image is not deleted. A captured image also cannot be deleted while another capture, sandbox, or snapshot still uses its files.

from daytona import Daytona
daytona = Daytona()
daytona.v2.images.delete("{imageId}")
  • images.delete takes the image ID, img_....

Read the output of an image build. Following the log streams output while the build runs and ends when it finishes. Stopping the reader does not stop the build.

from daytona import Daytona
from daytona.v2 import ImageBuilder
daytona = Daytona()
image = daytona.v2.images.build(ImageBuilder.from_dockerfile("FROM python:3.12-slim"), name="my-awesome-image")
daytona.v2.images.follow_build_logs(image.id, on_logs=lambda chunk: print(chunk, end=""))
ParameterTypeDescription
timeoutfloatBounds the follow in seconds. When the timeout expires, the call raises BuildLogInterruptedError instead of returning. The cursor of the error resumes the follow. By default, there is no deadline.

The response has the following fields:

FieldDescription
reasonThe reason is terminal, deadline, not_applicable, resource_deleted, or unknown.
cursorResumes the follow after the last output. Pass this value in a later call.
  • follow_build_logs returns status, reason, output_complete, and cursor.

Check an image build’s progress. An image moves from pending to building and ends as ready or failed, with a failure reason when it fails.

from daytona import Daytona
daytona = Daytona()
image = daytona.v2.images.get("{imageId}")
print(image.id, image.status, image.error)