How images are staged
Staging puts your container image on the instance that runs your image. Hangar refuses an image that fails a check before any container starts.
This page covers the two forms in which Hangar stores an image. The page also covers how a GPU slot and a CPU sandbox session stage each form, which platform of a multi-platform image each one runs, and the checks that refuse an image.
The two forms of a stored image
Hangar stores every image in Sydney, sealed under your organisation's key, in one of two forms:
- An OCI image layout archive, stored as one object.
hangar upload --image ARCHIVEsends this form. - A pushed image, stored as one object for each blob. A push to the Hangar registry makes this form, with
hangar upload,docker pushorcrane. The blobs are the manifest, the config and each layer. A multi-platform image also has an index above the manifest. Two images that share a layer share one stored object.
Hangar stages either form by the digest that you approved. Hangar never stages a tag.
What staging does
For each image that a job or a session names, Hangar orders the stored objects that the image needs. The worker on the instance then does these four things:
- The worker fetches each object, decrypts the object on the instance and checks the object against its SHA-384, as the worker does for your data.
- For a pushed image, the worker checks each blob against the SHA-256 digest that names the blob. The worker checks the first blob against the approved digest. The worker then writes the blobs into one OCI image layout archive. The archive must contain the image exactly: every blob that the manifest names, and nothing else.
- The worker reads the archive again, hashes every layer that the archive contains, and runs the preflight.
- The worker imports the image into containerd under the approved digest.
The worker fetches at most four blobs of a pushed image at a time. Each blob leaves the working directory as the blob enters the archive. The worker removes the working directory on every path out.
The platform each instance runs
| Where it runs | Platform | From a multi-platform image |
|---|---|---|
| A GPU slot | linux/amd64 | the linux/amd64 entry |
A CPU sandbox session, hosted-cpu-syd | linux/arm64 | the linux/arm64 entry, and no other |
Hangar refuses an image that is built for a different platform from the platform of the instance, with preflight_architecture. A sandbox session reads a pushed image's config before any layer. Hangar therefore fetches no layer of an image that the session refuses. Hangar refuses an index with no linux/arm64 entry from the index alone.
Hangar checks each platform of a multi-platform image when the image is pushed. Hangar records a result for each platform (preflight_detail.platforms). Hangar accepts a GPU job when the linux/amd64 result passed. Hangar opens a sandbox session when the linux/arm64 result passed and the image fits the CPU pool's allowance of 8 GiB compressed.
The worker checks the platform and the allowance again on the bytes that the worker stages. A sandbox session checks a pushed image's layer sizes before the session fetches a layer. For each layer, the session uses the larger of two sizes: the size that the manifest declares and the size that Hangar holds.
How each instance reaches the store
- A GPU slot reads its objects with per-slot credentials. Hangar issues the credentials after the instance attests. The credentials reach exactly the slot's objects. A credential lasts 15 minutes. The worker renews the credential before any fetch or upload would start with less than its refresh margin left. The worker also renews the credential between the parts of an upload in parts. Staging and sealing therefore run for as long as their bytes take.
- A CPU sandbox session has no storage credential. The control plane gives the session one presigned GET for each object that its images need. Each URL is valid for 15 minutes and for that one object. The worker on the host fetches through these URLs. The session's containers cannot reach the store.
When less than 3 minutes of an image's URLs is left, or the store refuses a URL, the worker asks the control plane for new URLs for that image's objects. The worker sends POST /v1/sandbox-agent/session/image-urls, with the session's own credential, while the session runs. The control plane gives a URL only for an object that the session manifest names. A renewed URL opens the same object. The worker checks every object against its digests after each fetch.
Refusals
| Code | What happened |
|---|---|
image_unresolved | Your organisation has no image with that digest. |
image_manifest_incomplete | The image's manifest refers to a blob that your organisation no longer stores. |
data_fetch_failed | The worker could not fetch an object after three attempts. |
data_digest_mismatch | An object, or a blob, does not match the digest that names it. |
preflight_architecture | The image is not built for the platform that the instance runs. |
preflight_too_large | The image is larger than the instance's allowance: 200 GB for a GPU slot, 8 GiB for a sandbox session. |
preflight_media_type | A manifest, config or layer is not a container image type. |