Skip to main content
Sailbox images define the root filesystem used to start a VM. Start from a Debian base image, then chain build steps to install dependencies, copy local files, run setup commands, and set environment variables.
import sail

image = (
    sail.Image.debian_arm64
    .apt_install("git", "curl")
    .pip_install("requests")
    .add_local_dir("./app", "/opt/app", ignore=["*.pyc", "__pycache__/"])
    .env({"APP_ENV": "production"})
)
Image definitions are immutable. Each method returns a new image definition, so you can safely reuse a base image across multiple variants.

Base images

Use a Debian base image for the target architecture:
arm_image = sail.Image.debian_arm64
amd_image = sail.Image.debian_amd64
sail.Image.debian_arm is an alias for sail.Image.debian_arm64. sail.Image.debian_amd is an alias for sail.Image.debian_amd64.

Install Python packages

Use pip_install() for Python dependencies:
image = sail.Image.debian_arm64.pip_install(
    "requests",
    "beautifulsoup4",
)
Package installation happens at image build time, before any Sailbox starts. This is usually faster and more reproducible than installing packages in every new VM with exec().

Add local files

Use add_local_file() to copy a single local file into the image:
image = sail.Image.debian_arm64.add_local_file(
    "./config.json",
    "/etc/demo/config.json",
    mode=0o600,
)
Use add_local_dir() to copy a directory tree:
image = sail.Image.debian_arm64.add_local_dir(
    "./app",
    "/opt/demo-app",
    ignore=["*.pyc", "__pycache__/"],
)
Remote paths must be absolute POSIX paths. Directory uploads preserve file modes from the local filesystem and skip symlinks. The ignore argument accepts gitignore-style patterns or a path to an ignore file. Use image files for source code, static assets, and configuration that should exist before boot. Use Filesystem for runtime inputs, outputs, logs, and data that changes per Sailbox.

Install system packages

Use apt_install() for Debian packages:
image = sail.Image.debian_arm64.apt_install(
    "git",
    "curl",
    "openssh-server",
)

Run shell commands

Use run_commands() for shell commands that should execute during the image build:
image = (
    sail.Image.debian_arm64
    .apt_install("python3")
    .pip_install("requests")
    .run_commands("python3 -m pip show requests >/tmp/requests.txt")
)
Build commands run once while the image is prepared. They do not run each time a Sailbox starts.

Set environment variables

Use env() for environment variables that should be present in Sailboxes created from the image:
image = sail.Image.debian_arm64.env(
    {
        "APP_ENV": "demo",
        "LOG_LEVEL": "info",
    }
)

Create a Sailbox from an image

Pass the image definition to Sailbox.create():
app = sail.App.find(name="custom-image-demo", mint_if_missing=True)

image = (
    sail.Image.debian_arm64
    .apt_install("git", "curl")
    .pip_install("requests")
    .add_local_dir("./app", "/opt/app", ignore=["*.pyc", "__pycache__/"])
    .env({"APP_ENV": "custom-image-demo"})
)

sb = sail.Sailbox.create(
    app=app,
    image=image,
    name="custom-image-demo",
    image_build_timeout=1800,
)
Sailbox.create() builds the image first if it has not already been built, then starts the VM from that image.

Build an image ahead of time

Use build() when you want to prepare the image before creating a Sailbox:
image = (
    sail.Image.debian_arm64
    .apt_install("git")
    .pip_install("requests")
    .build(timeout=1800)
)

sb = sail.Sailbox.create(
    app=app,
    image=image,
    name="prebuilt-image-demo",
)

Image caching

Sail caches image builds per organisation by content. If the base image, build steps, environment variables, and uploaded file contents are unchanged, later Sailboxes can reuse the existing image instead of rebuilding it. A change to any build step or local file content creates a new image.