Register a custom image
You're going to register a custom ext4 image baked from an OCI source (e.g. docker.io/r-base:4.4), wait for it to fan out to your tenant's workers, and then create a bunker from it.
Roughly 5 minutes plus the bake time (a few seconds to a couple of minutes depending on image size).
1. Decide the image's shape#
Settle these before the API call:
- Build source. OCI (
{kind: "oci", ref: "docker.io/r-base:4.4"}) for anything pullable from a registry.tarfor tarballs your worker can read locally — air-gapped deployments, hand-built rootfs. - Size.
size_mibis the cap on the resulting ext4 file. Too small →mkfs.ext4errors at bake time. Pick generously; 2048 is a sensible floor for non-minimal images. - Defaults.
default_cpu_millicores,default_memory_mb,default_disk_mbare applied when a caller creates a bunker from this image without overriding. Set them to a sensible "this image needs at least this to function" floor. - Scope.
tenant(default) — only this tenant sees it.partner— every tenant under your partner.platform— visible to every tenant; only super-admins can register at this scope. - Lazy pull.
lazy_pull: truelets the scheduler place a bunker on a worker that doesn't have the image cached yet (slower first boot). The defaultfalserequires the image to bereadyon a worker before that worker is eligible.
You need scaibunker:images:manage to register a new image.
2. Register the image#
POST to /images with the build source, size cap, and defaults. The response includes the new image id plus a warm summary if any workers were already in scope for fan-out.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
The response includes a warm object summarising the fan-out: {queued, ready, failed, skipped}. If your tenant's availability-group setup already covers some workers, those will show as ready or queued immediately.
3. Watch fan-out progress#
GET the image's cache view to see one row per targeted worker. Poll until every row reports status: ready.
1 2 | |
You'll get one row per worker that's been targeted, with status in pending, building, ready, failed, or evicted. Re-poll until every row is ready — at that point, every worker in the targeting groups has the ext4 cached and can launch bunkers from it instantly.
If a worker shows failed, the error field carries the worker's response (registry auth issue, size cap hit, OOM during mkfs, etc.). Fix the cause and re-trigger:
1 2 | |
The warm route is idempotent — workers that already have the image come back instantly.
4. Assign to an availability group (if needed)#
If your tenant's images don't yet sit in any group, the fan-out will have done nothing. Create a group and put the image in it:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Adding a worker to the group (POST /availability-groups/{id}/workers) will then trigger a warm of every image already in the group on that newly-joined worker — same machinery, no extra calls.
5. Wait for the security scan#
Every registered image is scanned automatically. The image row carries:
scan_status: pending— queued; the background task runs every 2 minutes.scan_status: passed— no critical or high CVEs.scan_status: failed— CVEs found, or the scanner itself failed (missing binary, registry error). Failures don't block bunker creation; the status is informational.scan_status: skipped— image source has no scannable OCI ref.
To re-scan on demand:
1 2 | |
6. Create a bunker from the new image#
Reference the image by name in the bunker create. The scheduler will pick a worker with the image cached ready.
1 2 3 4 5 6 7 8 | |
The scheduler will pick a worker with the image cached ready. If none yet, the call fails with NO_SUITABLE_WORKER — wait for the fan-out to complete, or set lazy_pull: true on the image to allow placement on cold workers.
7. Deactivate when retiring#
When the image is end-of-life, deactivate it instead of leaving it around:
1 2 | |
Deactivation is a soft-delete: existing bunkers keep running, but new bunkers can't be created from it. Per-worker cache entries get garbage-collected by the scanner background task on its next sweep.
Done#
You have a custom image baked, fanned out to your workers, scanned, and ready for production. Iterate the source by registering a new image with a different name — there's no in-place update; you version by name.