Back to Microsandbox

Images

docs/sdk/python/images.mdx

0.6.921.2 KB
Original Source

Configure sandbox image sources and manage the local OCI image cache.

Image

Factory for sandbox image sources.

<span className="msb-recv">Image.</span><span className="msb-hn">oci()</span>

python
@staticmethod
def oci(
    reference: str,
    *,
    root_disk: RootDiskConfig | int | None = None,
    upper_size_mib: int | None = None,
) -> ImageSource
<Accordion title="Example">
python
from microsandbox import Image, RootDisk, Sandbox

sb = await Sandbox.create(
    "api",
    image=Image.oci("python:3.12", root_disk=RootDisk.managed(8192)),
)
</Accordion>

Create an OCI image rootfs source. Use root_disk to configure its writable layer with a RootDisk factory result. An integer is shorthand for a managed disk of that size in MiB.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>reference</code><span className="msb-type">str</span></div> <div className="msb-param-desc">OCI image reference, e.g. <code>"python:3.12"</code>.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>root_disk</code><span className="msb-type">RootDiskConfig | int | None</span></div> <div className="msb-param-desc">Writable root disk configuration or managed-disk size in MiB.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>upper_size_mib</code><span className="msb-type">int | None</span></div> <div className="msb-param-desc">Deprecated managed-disk size alias. Use <code>root_disk=RootDisk.managed(...)</code>.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#imagesource">ImageSource</a></div> <div className="msb-param-desc">Rootfs source for <code>image=</code>.</div> </div> </div>

<span className="msb-recv">Image.</span><span className="msb-hn">bind()</span>

python
@staticmethod
def bind(path: str) -> ImageSource
<Accordion title="Example">
python
sb = await Sandbox.create("api", image=Image.bind("/srv/rootfs"))
</Accordion>

Create a rootfs source that binds a host directory as the guest root filesystem.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">str</span></div> <div className="msb-param-desc">Host directory to use as the rootfs.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#imagesource">ImageSource</a></div> <div className="msb-param-desc">Rootfs source for <code>image=</code>.</div> </div> </div>

<span className="msb-recv">Image.</span><span className="msb-hn">disk()</span>

python
@staticmethod
def disk(path: str, *, fstype: str | None = None) -> ImageSource
<Accordion title="Example">
python
sb = await Sandbox.create(
    "api",
    image=Image.disk("/data/root.qcow2", fstype="ext4"),
)
</Accordion>

Create a rootfs source backed by a disk image. The format is inferred from the file extension. Pass fstype when the filesystem type cannot be auto-detected.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">str</span></div> <div className="msb-param-desc">Path to the disk image (e.g. <code>.qcow2</code>, <code>.raw</code>, <code>.vmdk</code>).</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>fstype</code><span className="msb-type">str | None</span></div> <div className="msb-param-desc">Filesystem type, e.g. <code>"ext4"</code>. <code>None</code> auto-detects.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#imagesource">ImageSource</a></div> <div className="msb-param-desc">Rootfs source for <code>image=</code>.</div> </div> </div> <p className="msb-member-group">Cache management</p>

These static methods inspect and prune images already pulled into the local OCI cache. They require a local backend; on a cloud backend they raise UnsupportedError.

<span className="msb-recv">Image.</span><span className="msb-hn">get()</span>

python
@staticmethod
async def get(reference: str) -> ImageHandle
<Accordion title="Example">
python
handle = await Image.get("python:3.12")
print(handle.reference, handle.layer_count)
</Accordion>

Fetch one cached image by reference. Raises ImageNotFoundError when the image is not present in the local cache.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>reference</code><span className="msb-type">str</span></div> <div className="msb-param-desc">Image reference to look up.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#imagehandle">ImageHandle</a></div> <div className="msb-param-desc">Handle to the cached image.</div> </div> </div>

<span className="msb-recv">Image.</span><span className="msb-hn">list()</span>

python
@staticmethod
async def list() -> list[ImageHandle]
<Accordion title="Example">
python
for image in await Image.list():
    print(image.reference, image.size_bytes)
</Accordion>

Return every cached image.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#imagehandle">list[ImageHandle]</a></div> <div className="msb-param-desc">All cached image handles.</div> </div> </div>

<span className="msb-recv">Image.</span><span className="msb-hn">inspect()</span>

python
@staticmethod
async def inspect(reference: str) -> ImageDetail
<Accordion title="Example">
python
detail = await Image.inspect("python:3.12")
print(detail.handle.reference)
for layer in detail.layers:
    print(layer.position, layer.diff_id)
</Accordion>

Return handle metadata plus the parsed OCI config and per-layer detail.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>reference</code><span className="msb-type">str</span></div> <div className="msb-param-desc">Image reference to inspect.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#imagedetail">ImageDetail</a></div> <div className="msb-param-desc">Handle, OCI config, and layers.</div> </div> </div>

<span className="msb-recv">Image.</span><span className="msb-hn">remove()</span>

python
@staticmethod
async def remove(reference: str, *, force: bool = False) -> None
<Accordion title="Example">
python
await Image.remove("python:3.12", force=True)
</Accordion>

Delete a cached image. When force is False, an image still referenced by one or more sandboxes raises ImageInUseError; pass force=True to remove it anyway.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>reference</code><span className="msb-type">str</span></div> <div className="msb-param-desc">Image reference to delete.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>force</code><span className="msb-type">bool</span></div> <div className="msb-param-desc">Remove even if still referenced. Default <code>False</code>.</div> </div> </div>

<span className="msb-recv">Image.</span><span className="msb-hn">prune()</span>

python
@staticmethod
async def prune() -> ImagePruneReport
<Accordion title="Example">
python
report = await Image.prune()
print(f"{report.layers_removed} layers, {report.bytes_reclaimed} bytes")
</Accordion>

Remove cached image data that is not used by any sandbox or indexed snapshot. The returned report counts the removed refs, manifests, layers, fsmeta files, and VMDK files, plus any measured bytes reclaimed.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#imageprunereport">ImagePruneReport</a></div> <div className="msb-param-desc">Counts of removed data and bytes reclaimed.</div> </div> </div> <Accordion title="Example">
python
report = await Image.prune()
print(f"{report.layers_removed} layers, {report.bytes_reclaimed} bytes")
</Accordion>

<span className="msb-recv">Image.</span><span className="msb-hn">load()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
python
@staticmethod
async def load(input_path: str, *, tag: str | None = None) -> list[ImageHandle]

Import images from a local archive into the cache. Accepts docker save tarballs and OCI Image Layout archives, so locally built images can be used without going through a registry.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>input_path</code><span className="msb-type">str</span></div> <div className="msb-param-desc">Path to the archive file, or <code>"-"</code> to read the archive from stdin.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>tag</code><span className="msb-type">str | None</span></div> <div className="msb-param-desc">Extra reference applied to the first image in the archive.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#imagehandle">list[ImageHandle]</a></div> <div className="msb-param-desc">A handle for every image reference imported.</div> </div> </div> <Accordion title="Example">
python
# docker save my-image:latest -o my-image.tar
images = await Image.load(input_path="my-image.tar", tag="app:local")
for image in images:
    print(image.reference, image.layer_count)

# Or pipe it in: docker save my-image:latest | python app.py
images = await Image.load(input_path="-")
</Accordion>

<span className="msb-recv">Image.</span><span className="msb-hn">save()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
python
@staticmethod
async def save(
    reference: str | Sequence[str],
    *,
    output_path: str,
    format: ImageArchiveFormat = ImageArchiveFormat.DOCKER,
) -> None

Export one or more cached images to an archive file. Raises ImageNotFoundError when any reference is not in the local cache, and ValueError for an empty reference list.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>reference</code><span className="msb-type">str | Sequence[str]</span></div> <div className="msb-param-desc">Cached image reference to export, or a sequence of references written into the same archive.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>output_path</code><span className="msb-type">str</span></div> <div className="msb-param-desc">File path to write the archive to.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>format</code><a className="msb-type" href="#imagearchiveformat">ImageArchiveFormat</a></div> <div className="msb-param-desc">Archive layout. Defaults to <code>DOCKER</code>.</div> </div> </div> <Accordion title="Example">
python
from microsandbox import ImageArchiveFormat

await Image.save("python:3.12", output_path="python.tar")
await Image.save(
    "python:3.12",
    output_path="python-oci.tar",
    format=ImageArchiveFormat.OCI,
)
await Image.save(["python:3.12", "app:local"], output_path="bundle.tar")
</Accordion>

ImageHandle

<div className="msb-tags"><span className="msb-tag is-type">class</span></div> <p className="msb-backref">Returned by <a href="#image-get">get()</a> · <a href="#image-list">list()</a> · <a href="#image-load">load()</a></p>

A lightweight handle to a cached OCI image, returned by Image.get(), Image.list(), and Image.load(). Properties are read-only attributes; the two methods are async.

<span className="msb-recv">handle.</span><span className="msb-hn">reference</span>

str

Image reference

<span className="msb-recv">handle.</span><span className="msb-hn">size_bytes</span>

int \| None

Total size in bytes, or None when unknown

<span className="msb-recv">handle.</span><span className="msb-hn">manifest_digest</span>

str \| None

Content-addressable manifest digest

<span className="msb-recv">handle.</span><span className="msb-hn">architecture</span>

str \| None

Resolved architecture

<span className="msb-recv">handle.</span><span className="msb-hn">os</span>

str \| None

Resolved operating system

<span className="msb-recv">handle.</span><span className="msb-hn">layer_count</span>

int

Number of layers

<span className="msb-recv">handle.</span><span className="msb-hn">last_used_at</span>

float \| None

Last referenced time, milliseconds since epoch

<span className="msb-recv">handle.</span><span className="msb-hn">created_at</span>

float \| None

First-pulled time, milliseconds since epoch

<span className="msb-recv">handle.</span><span className="msb-hn">inspect()</span>

python
await inspect()

Fetch full detail for this image

<p className="msb-label">Returns</p>

ImageDetail

<span className="msb-recv">handle.</span><span className="msb-hn">remove()</span>

python
await remove(*, force=False)

Delete this image (raises ImageInUseError unless force)

RootDisk

Factory for writable OCI root disk configurations.

python
from microsandbox import DiskImageFormat, RootDisk

managed = RootDisk.managed(8192)
temporary = RootDisk.tmpfs(512)
existing = RootDisk.disk(
    "/data/upper.raw",
    format=DiskImageFormat.RAW,
    fstype="ext4",
)

<span className="msb-recv">RootDisk.</span><span className="msb-hn">managed()</span>

python
managed(size_mib=None)

Microsandbox-managed sparse ext4 disk

<p className="msb-label">Returns</p>

RootDiskConfig

<span className="msb-recv">RootDisk.</span><span className="msb-hn">tmpfs()</span>

python
tmpfs(size_mib=None)

Ephemeral RAM-backed upper layer

<p className="msb-label">Returns</p>

RootDiskConfig

<span className="msb-recv">RootDisk.</span><span className="msb-hn">disk()</span>

python
disk(path, *, format=None, fstype=None)

User-supplied writable disk image

<p className="msb-label">Returns</p>

RootDiskConfig

Types

ImageSource

<p className="msb-backref">Returned by <a href="#image-oci">oci()</a> · <a href="#image-bind">bind()</a> · <a href="#image-disk">disk()</a></p>

Explicit rootfs image source. Build one with Image.oci(), Image.bind(), or Image.disk(), then pass it as the image= kwarg to Sandbox.create(). A frozen dataclass; treat its fields as opaque.

FieldTypeDescription
_typeImageSourceKindSource kind
_pathstr | NoneHost path for bind / disk sources
_referencestr | NoneOCI reference for oci sources
_upper_size_mibint | NoneWritable overlay upper size in MiB (OCI only)
_fstypestr | NoneFilesystem type for disk sources
_formatDiskImageFormat | NoneDisk image format (inferred from extension)

RootDiskConfig

Frozen root disk configuration produced by RootDisk.

FieldTypeDescription
kindRootDiskKindRoot disk implementation
size_mibint | NoneManaged disk or tmpfs size
pathstr | NoneUser-supplied disk image path
formatDiskImageFormat | NoneDisk image format
fstypestr | NoneInner filesystem type

ImageDetail

<p className="msb-backref">Returned by <a href="#image-inspect">inspect()</a> · <a href="#imagehandle">ImageHandle.inspect()</a></p>

Full detail for a cached image: the core handle, the parsed OCI config block, and per-layer metadata.

PropertyTypeDescription
handleImageHandleCore cached image metadata
configImageConfigDetail | NoneParsed OCI config block
layerslist[ImageLayerDetail]Layers in bottom-to-top order

ImageConfigDetail

<p className="msb-backref">Used by <a href="#imagedetail">ImageDetail.config</a></p>

OCI image config fields extracted from the local cache.

PropertyTypeDescription
digeststrConfig blob digest
envlist[str]Environment variables (KEY=value)
cmdlist[str] | NoneDefault command
entrypointlist[str] | NoneImage entrypoint
working_dirstr | NoneDefault working directory
userstr | NoneDefault user
labelsdict[str, Any] | NoneOCI labels
stop_signalstr | NoneConfigured stop signal

ImageLayerDetail

<p className="msb-backref">Used by <a href="#imagedetail">ImageDetail.layers</a></p>

Metadata for a single image layer.

PropertyTypeDescription
diff_idstrUncompressed layer diff id
blob_digeststrCompressed blob digest
media_typestr | NoneLayer media type
compressed_size_bytesint | NoneCompressed size in bytes
erofs_size_bytesint | NoneSize of the generated EROFS sidecar in bytes
positionintLayer position (bottom to top)

ImagePruneReport

<p className="msb-backref">Returned by <a href="#image-prune">prune()</a></p>

Summary of cached image data removed by Image.prune().

PropertyTypeDescription
image_refs_removedintNumber of image refs removed
manifests_removedintNumber of manifests removed
layers_removedintNumber of layer blobs removed
fsmeta_removedintNumber of fsmeta sidecar files removed
vmdk_removedintNumber of VMDK files removed
bytes_reclaimedint | NoneMeasured bytes reclaimed, or None when not measured

DiskImageFormat

<p className="msb-backref">Used by <a href="#imagesource">ImageSource._format</a></p>

Disk image container format.

MemberValueDescription
DiskImageFormat.QCOW2"qcow2"QEMU copy-on-write v2
DiskImageFormat.RAW"raw"Raw block image
DiskImageFormat.VMDK"vmdk"VMware disk image

ImageArchiveFormat

<p className="msb-backref">Used by <a href="#image-save">Image.save(format=...)</a></p>

Archive layout used when exporting cached images.

MemberValueDescription
ImageArchiveFormat.DOCKER"docker"Docker archive compatible with docker load
ImageArchiveFormat.OCI"oci"OCI Image Layout archive

ImageSourceKind

<p className="msb-backref">Returned in <a href="#imagesource">ImageSource._type</a></p>

Root filesystem source kind.

MemberValueDescription
ImageSourceKind.OCI"oci"OCI image reference
ImageSourceKind.BIND"bind"Host directory bind source
ImageSourceKind.DISK"disk"Host disk-image source

RootDiskKind

<p className="msb-backref">Returned in <a href="#rootdiskconfig">RootDiskConfig.kind</a></p>

Writable OCI root disk implementation.

MemberValueDescription
RootDiskKind.MANAGED"managed"Microsandbox-managed sparse ext4 disk
RootDiskKind.TMPFS"tmpfs"Ephemeral RAM-backed upper layer
RootDiskKind.DISK_IMAGE"disk-image"User-supplied writable disk image

Errors

Image operations raise these typed exceptions, all subclasses of MicrosandboxError.

ExceptionRaised when
ImageNotFoundErrorThe image reference could not be resolved in the local cache
ImageInUseErrorThe image is still referenced by one or more sandboxes (and force was not set)
ImagePullFailedErrorAn image pull failed
UnsupportedErrorCache operations were attempted on a backend that lacks a local cache