Skip to main content
Builds turn a template builder into a reusable template ref.
from nullspace import Template, default_build_logger

build = Template.build(
    builder,
    name="my-template",
    tags=["stable"],
    cpu_count=4,
    memory_mb=2048,
    disk_mb=16384,
    skip_cache=False,
    on_log_entry=default_build_logger(),
)

print(build.status, build.name)
cpu_count, memory_mb, disk_mb, internet_access, build_backend, build_secrets, and skip_cache are available on both Template.build() and Template.build_in_background(). disk_mb sets the minimum rootfs size (MB) baked into the template. The build VM’s rootfs is grown to this size before its snapshot is captured, so every sandbox created from the template — cold create, warm-pool checkout, fork, or resume — inherits the larger disk. Use it for workloads that need local scratch space (cloning large repos, build artifacts). Omit it to use the default headroom.
build = Template.build(
    builder,
    name="offline-template",
    internet_access=False,
)

Background Builds

build = Template.build_in_background(builder, name="my-template", tags=["next"])
snapshot = build.get_status()
print(snapshot.build.status)

finished = build.wait_until_terminal()
print(finished.build.status)

CLI

nullspace template build --from-python-image 3.12 --name my-template --tag stable --cpu-count 4 --memory-mb 2048
nullspace template build --from-python-image 3.12 --name offline-template --no-internet-access
nullspace template build --from-dockerfile ./Dockerfile --name docker-template
nullspace template build --from-python-image 3.12 --name my-template --tag next --background
nullspace template wait tb_... --poll-interval-ms 500
Dockerfile builds use BuildKit. --backend buildkit is optional for Dockerfile input; --backend native is rejected for Dockerfile builds. For BuildKit Dockerfile builds, internet_access=False maps to BuildKit’s network-disabled mode. Private registry pulls and package installation steps that need outbound access will fail unless their inputs are already available from an accessible cache or local build context.

BuildKit Secrets

BuildKit Dockerfile builds can receive request-time secrets for RUN --mount=type=secret instructions through the Python SDK, CLI, or HTTP API. Secret values are written as temporary files on the build worker, passed to buildctl with --secret, and are not stored in build definitions, cache keys, context manifests, logs, or status metadata. CLI dry-run/render/error output redacts request-time secret values.
builder = (
    Template.from_dockerfile_content(
        "FROM node:20\nRUN --mount=type=secret,id=npm_token npm ci"
    )
    .add_build_secret_env("npm_token", "NPM_TOKEN")
)

Template.build(builder, name="private-npm")
nullspace template build \
  --from-dockerfile ./Dockerfile \
  --name private-npm \
  --build-secret-env npm_token=NPM_TOKEN
{
  "name": "private-npm-template",
  "dockerfile": "FROM node:20\nRUN --mount=type=secret,id=npm_token npm config set //registry.npmjs.org/:_authToken=$(cat /run/secrets/npm_token)",
  "build_secrets": [
    {
      "id": "npm_token",
      "value": "request-time-token",
      "source": "env"
    }
  ]
}
source is a client-side hint (value, env, or file); SDKs and CLIs resolve env/file inputs before submission. Native template builds reject build_secrets. Retries of builds that used secrets must provide fresh values for the same secret IDs, for example nullspace template retry tb_... --build-secret-env npm_token=NPM_TOKEN.