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-layoutandindex.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.
- OCI image example module - Source for the worked busybox image spec and the exported views.
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.
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) packagebash-interactive - node
tool:tar(tool) packagegnutar - node
tool:coreutils(tool) packagecoreutils - node
operation:assemble-rootfs-busybox(operation) viabash - node
operation:tar-layer-busybox(operation) viabash - node
operation:write-config(operation) viabash - node
operation:write-manifest(operation) viabash - node
operation:write-index(operation) viabash - node
operation:verify-blobs(operation) viabash - node
operation:clean-scratch(operation) viabash - node
operation:archive-layout(operation) viabash - 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-busyboxwithbash - run
tar-layer-busyboxwithbash - run
write-configwithbash - run
write-manifestwithbash - run
write-indexwithbash - run
verify-blobswithbash - run
clean-scratchwithbash - run
archive-layoutwithbash - descriptor
busybox-shell-oci-image - transform
oci-layout(json) - transform
index(json) - transform
blobs(tree) - transform
oci-archive(tar) - materialize
busybox-shell-oci-imagewithrunCommand - 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 pipefailtar-layer-busybox:bash -c 'set -euo pipefailwrite-config:bash -c 'set -euo pipefailwrite-manifest:bash -c 'set -euo pipefailwrite-index:bash -c 'set -euo pipefailverify-blobs:bash -c 'set -euo pipefailclean-scratch:bash -c 'set -euo pipefailarchive-layout:bash -c 'set -euo pipefail
Plan Shell Excerpt
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 keysarchitecture,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