Skip to main content
Version: Next 🚧

Artifact References

When you add an image to the store, the reference you type on the command line is not always the reference the store records. Missing registries, namespaces, and tags are filled in with defaults, and the resulting name is what hauler store info displays. This ensures that artifact references are OCI-compliant.

This guide traces how an image reference is transformed by hauler store add image or hauler store sync. The normalization from the argument you provide, to the annotations written on the stored OCI artifact, to the reference shown back to you is outlined to ensure predictable behavior with Hauler.

How It Works​

Every reference passed to hauler store add image moves through three stages:

  1. Parsed for fetching. A reference without a registry resolves to Docker Hub. The registry defaults to index.docker.io, a single-segment repository gains the library/ namespace, and a missing tag becomes latest. This fully-qualified name is what Hauler pulls, allowing a command such as hauler store add image nginx to correctly pull the image from index.docker.io/library/nginx:latest.

  2. Recorded as annotations. The stored artifact carries three annotations, all derived from the fully-qualified reference:

    AnnotationValue
    org.opencontainers.image.ref.nameThe reference with the registry prefix stripped (OCI standard)
    io.containerd.image.nameThe canonical form of the reference, registry included
    hauler.dev/original-refThe full original reference, captured at add-time for provenance
  3. Resolved for display. hauler store info prefers io.containerd.image.name, which already holds a complete registry/repository:tag. It falls back to org.opencontainers.image.ref.name only when that annotation is absent.

Examples​

Example 1: Bare Image Name​

hauler store add image nginx
StageValue
Inputnginx
Fetched asindex.docker.io/library/nginx:latest
org.opencontainers.image.ref.namelibrary/nginx:latest
io.containerd.image.namedocker.io/library/nginx:latest
hauler.dev/original-refindex.docker.io/library/nginx:latest
Displayed by store infodocker.io/library/nginx:latest

The input is fully expanded to pull from the Docker Hub registry, the library/ namespace, and the latest tag.


Example 2: Namespaced Image Name​

hauler store add image rancher/rancher
StageValue
Inputrancher/rancher
Fetched asindex.docker.io/rancher/rancher:latest
org.opencontainers.image.ref.namerancher/rancher:latest
io.containerd.image.namedocker.io/rancher/rancher:latest
hauler.dev/original-refindex.docker.io/rancher/rancher:latest
Displayed by store infodocker.io/rancher/rancher:latest

A two-segment name already has a namespace, so library/ is not added. Only the registry and the latest tag are inferred.


Example 3: Fully Qualified Image Name​

hauler store add image private.registry.com/my-image:dev
StageValue
Inputprivate.registry.com/my-image:dev
Fetched asprivate.registry.com/my-image:dev
org.opencontainers.image.ref.namemy-image:dev
io.containerd.image.nameprivate.registry.com/my-image:dev
hauler.dev/original-refprivate.registry.com/my-image:dev
Displayed by store infoprivate.registry.com/my-image:dev

Nothing is inferred, because the registry and tag are both explicit. Note that stripping the registry leaves org.opencontainers.image.ref.name as a single-segment my-image:dev. Because the regsitry is not docker.io, library/ is not inferred.


Example 4: Image Name with a Rewrite​

hauler store add image nginx --rewrite custom-nginx

The image is stored exactly as in Example 1, then retagged in place. Because custom-nginx specifies no tag, the source tag (latest) is carried over, and because it specifies no registry, the source registry is preserved.

StageValue
Inputnginx with --rewrite custom-nginx
org.opencontainers.image.ref.name (after rewrite)custom-nginx:latest
io.containerd.image.name (after rewrite)index.docker.io/custom-nginx:latest
hauler.dev/original-ref (after rewrite)index.docker.io/library/nginx:latest (unchanged)
Displayed by store infoindex.docker.io/custom-nginx:latest

hauler.dev/original-ref is intentionally left alone so the original pullable reference is preserved even after a rewrite. Without explicit specification, library/ is not preserved in the rewrite since the index.docker.io/library path will not resolve with the new reference. See the Rewriting Artifacts guide for more on the --rewrite flag.


Summary​

Commandstore info displayStore key
hauler store add image nginxdocker.io/library/nginx:latestlibrary/nginx:latest
hauler store add image rancher/rancherdocker.io/rancher/rancher:latestrancher/rancher:latest
hauler store add image private.registry.com/my-image:devprivate.registry.com/my-image:devmy-image:dev
hauler store add image nginx --rewrite custom-nginxindex.docker.io/custom-nginx:latestcustom-nginx:latest