# 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.

- [OCI image example module](/metaBuilder/examples/oci-image/source/builder.nix) - 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.

```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`

