Navigation

OCI image example

This tour builds a runnable OCI image layout from one static busybox layer. The builder vocabulary lives in the oci-image ornament; this example only supplies the image fields and shows the resulting views.

The worked artifact is a spec-conformant OCI layout (oci-layout, index.json, blobs/sha256/*) plus an image.oci.tar archive of the layout, all assembled at build time with the digests computed in the build sandbox.

Start from the artifact

The payload is pkgsStatic.busybox — a single musl-static layer with no runtime closure. The build produces:

  • oci-layout and index.json, the layout entry points.
  • blobs/sha256/<digest> for the layer tar, the image config, and the manifest — each blob named by its own sha256.
  • image.oci.tar, a deterministic tar of the layout for transports that want a single file.

Source files

These pages are the complete source for the worked example: the builder module plus the files it consumes.

Builder vocabulary

OciImageBuilder ornaments the generic BuilderSpec with the image fields (layers, entrypoint, cmd, env, exposedPorts, labels, architecture, os). The ociImage constructor compiles those fields into the assembly program, so the example stays at the domain surface.

nix
ociImage {
  name = "busybox-shell";
  layers = [
    { name = "busybox"; source = pkgs.pkgsStatic.busybox; }
  ];
  entrypoint = [ "/bin/sh" ];
}

Program walkthrough

The constructor lowers the image spec into named steps in digest-chain order: assemble the layer rootfs, tar it deterministically, render the config (embedding layer diff_ids), render the manifest (embedding config and layer digests and sizes), write the index last, re-hash every blob against its filename, clean the scratch directory, and archive the layout.

Because the steps are data, every fold renders them by name: dependency analysis, dry-run, plan-view, and self-documentation all show the same assembly. The smoke-test evidence travels with the spec and renders under the documentation's Evidence section.

One build, many views

The section below is generated from mb.program.introspect.run program. It is the internalized view of the image build: validation, dependency graph, dry-run, plan-view, descriptors, outputs, and materialization.

The same internalized program is interpreted several ways.

Validation

  • result: ok

Dependency Graph

  • nodes: 11
  • edges: 8
  • services: 0
  • node tool:bash (tool) package bash-interactive
  • node tool:tar (tool) package gnutar
  • node tool:coreutils (tool) package coreutils
  • node operation:assemble-rootfs-busybox (operation) via bash
  • node operation:tar-layer-busybox (operation) via bash
  • node operation:write-config (operation) via bash
  • node operation:write-manifest (operation) via bash
  • node operation:write-index (operation) via bash
  • node operation:verify-blobs (operation) via bash
  • node operation:clean-scratch (operation) via bash
  • node operation:archive-layout (operation) via bash
  • edge tool:bash -> operation:assemble-rootfs-busybox (uses-tool)
  • edge tool:bash -> operation:tar-layer-busybox (uses-tool)
  • edge tool:bash -> operation:write-config (uses-tool)
  • edge tool:bash -> operation:write-manifest (uses-tool)
  • edge tool:bash -> operation:write-index (uses-tool)
  • edge tool:bash -> operation:verify-blobs (uses-tool)
  • edge tool:bash -> operation:clean-scratch (uses-tool)
  • edge tool:bash -> operation:archive-layout (uses-tool)

Dry Run - Builder

  • tool bash
  • tool tar
  • tool coreutils
  • write oci-layout
  • run assemble-rootfs-busybox with bash
  • run tar-layer-busybox with bash
  • run write-config with bash
  • run write-manifest with bash
  • run write-index with bash
  • run verify-blobs with bash
  • run clean-scratch with bash
  • run archive-layout with bash
  • descriptor busybox-shell-oci-image
  • transform oci-layout (json)
  • transform index (json)
  • transform blobs (tree)
  • transform oci-archive (tar)
  • materialize busybox-shell-oci-image with runCommand
  • evidence smoke-test

Dry Run - Runtime

None.

Plan View

  • write write:oci-layout
  • run assemble-rootfs-busybox
  • run tar-layer-busybox
  • run write-config
  • run write-manifest
  • run write-index
  • run verify-blobs
  • run clean-scratch
  • run archive-layout
  • write:oci-layout: mkdir -p "$(dirname "$out/oci-layout")"
  • assemble-rootfs-busybox: bash -c 'set -euo pipefail
  • tar-layer-busybox: bash -c 'set -euo pipefail
  • write-config: bash -c 'set -euo pipefail
  • write-manifest: bash -c 'set -euo pipefail
  • write-index: bash -c 'set -euo pipefail
  • verify-blobs: bash -c 'set -euo pipefail
  • clean-scratch: bash -c 'set -euo pipefail
  • archive-layout: bash -c 'set -euo pipefail

Plan Shell Excerpt

sh
mkdir -p "$(dirname "$out/oci-layout")"
cat > "$out/oci-layout" <<'METABUILDER_HEREDOC_18f0797eab35a4597c1e9624aa4f15fd91f6254e5538c1e0d193b2a95dd4acc6'
{"imageLayoutVersion":"1.0.0"}
METABUILDER_HEREDOC_18f0797eab35a4597c1e9624aa4f15fd91f6254e5538c1e0d193b2a95dd4acc6
bash -c 'set -euo pipefail
mkdir -p "'"$out"'/.scratch/rootfs-busybox"
cp -a "$1"/. "'"$out"'/.scratch/rootfs-busybox/"
chmod -R u+w "'"$out"'/.scratch/rootfs-busybox"
' assemble-rootfs-busybox /nix/store/mm0g0g122n6pi28759dkkx8cfb2724by-busybox-static-x86_64-unknown-linux-musl-1.37.0
bash -c 'set -euo pipefail

Runtime Services

None.

Descriptors

  • descriptor busybox-shell-oci-image (payload keys architecture, entrypoint, exposedPorts, kind, labels, os)

Builder Self-Documentation

  • documented operations: 19
  • runtime services: 0

Materialized Outputs

  • oci-layout -> oci-layout (json)
  • index -> $out/index.json (json)
  • blobs -> $out/blobs (tree)
  • oci-archive -> $out/image.oci.tar (tar)

Materialization

  • derivation: busybox-shell-oci-image
  • outputs: 4
  • runtime artifacts: 0

Substrates

  • dockerfile: supported
  • shell: supported