Chapter 04Lesson 01~95 minutes

Images, Layers, Content-Addressable Storage, Manifests, Config Objects, and Image Identity: Concepts, Architecture, and Mental Model

Container images become operationally trustworthy only when you distinguish mutable names from immutable content. This lesson builds the image graph from a tag through an OCI index or manifest, config object, ordered layer descriptors, local content/snapshot storage, and finally the root filesystem a container receives.

Image identityOCI image graphManifestsLayersDigests

Learning objectives

  • Explain the path from a human-readable repository/tag through an OCI image index or image manifest to a config object and ordered layer descriptors.
  • Distinguish a tag, index digest, platform-manifest digest, config digest/Image ID, compressed layer digest, and uncompressed DiffID.
  • Explain why a container root filesystem is assembled from ordered immutable changesets plus a writable container layer rather than copied from one monolithic image file.
  • Use read-only Docker/Buildx inspection to determine the current platform, local image identity, RepoDigests, rootfs DiffIDs, and registry-side manifest structure.
  • Relate digest-level identity to reproducible CI/CD promotion, rollback, audit evidence, and supply-chain verification.
Chapter 04 evidence baseline — verified 2026-09-21. This chapter uses a free/local/disposable Docker path. Version-sensitive image behavior is inspected from the active daemon and registry rather than assumed. The standards baseline is OCI Image Specification v1.1.1; current Docker Engine 29 fresh installs default to the containerd image store, while upgraded hosts can differ. The lab image is a small Docker Official Image, and all immutable references are captured at run time rather than copied from prose.

1. The problem: a tag is a pointer, not the bytes

Humans prefer names such as busybox:1.37.0. Automation needs something stronger. A repository name and tag are registry lookup coordinates: the registry can later make that same tag resolve to different content. That mutability is useful for release channels such as stable or 3.24, but it is insufficient evidence for a forensic question such as “which exact image did production run?”

A content digest answers a different question. It is computed from the bytes of a specific content object. Change the object and the digest changes. OCI uses this property repeatedly: indexes reference manifests by descriptor digest; manifests reference config and layer blobs by digest; the config references uncompressed filesystem DiffIDs. Reproducibility begins by naming which digest you mean.

Identity rule: never write “the image digest” in an incident report without saying whether you mean an index digest, a platform-manifest digest, a local config/Image ID, or a layer digest. They identify different objects.

2. The image graph from name to runnable filesystem

The most useful mental model is a directed graph of immutable content with a mutable human-readable entry point. The tag is resolved first. A multi-platform publication normally resolves to an image index; the index chooses a platform-specific image manifest; that manifest references one config blob plus ordered layer descriptors. Docker then ensures the selected blobs exist locally and prepares snapshots/rootfs state that a container can use.

Human reference to container filesystem
flowchart TD
  A[repository:tag] -- mutable lookup --> B[registry/local resolver]
  B --> C{index or manifest?}
  C -- multi-platform --> D[OCI image index]
  D -- platform descriptor --> E[platform image manifest]
  C -- single-platform --> E
  E -- config descriptor --> F[image config JSON]
  E -- ordered layer descriptors --> G[compressed layer blobs]
  F -- rootfs.diff_ids --> H[uncompressed changeset identities]
  G -- pull + verify + unpack --> I[local content/snapshot store]
  I -- mount/assemble --> J[container read-only root filesystem]
  J -- plus writable layer --> K[running container filesystem view]
            

Each arrow represents a verification or selection boundary. The registry can return an index that contains many platforms, while the local daemon may materialize only one platform. A successful tag lookup does not prove the desired platform exists; a successful manifest fetch does not prove all layer blobs unpacked; local image presence does not prove a container is running.

3. Six identities that beginners often collapse into one

Identity What it names Mutable? Typical evidence
Repository + tag A named registry reference such as busybox:1.37.0. Yes; the publisher can move the tag. docker image ls, pull input.
Index digest A multi-platform OCI image index / Docker manifest list. No for those exact bytes. docker buildx imagetools inspect.
Manifest digest One platform-specific image manifest with config + layer descriptors. No for those exact bytes. Index child descriptor or registry response.
Config digest / Image ID The image configuration JSON used by the selected image; Docker exposes a content-addressed local image ID. No for those exact config bytes. docker image inspect --format '{{.Id}}'.
Layer digest A distributed layer blob as referenced by the manifest, commonly compressed. No. Manifest descriptors / imagetools --raw.
DiffID The digest of the uncompressed layer tar changeset. No. .RootFS.Layers in local image inspection / OCI config.

These values can all start with sha256: and still not be interchangeable. The algorithm prefix tells you how the digest is calculated, not what semantic object it identifies.

4. OCI descriptors: the repeated contract

OCI descriptors make the graph verifiable. A descriptor carries at least a media type, digest, and byte size. The consumer can know what representation to expect, how much content should arrive, and which cryptographic digest the received bytes must match. Indexes and manifests are therefore not vague catalogs; they are typed, content-addressed maps to other objects.

{
  "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
  "digest": "sha256:<content-hash>",
  "size": 123456
}

The example is schematic on purpose. Do not paste a digest from a tutorial and assume it identifies your platform's layer. Capture the descriptors returned for the exact image and platform you are inspecting.

5. Image index versus image manifest

An image index is a higher-level document whose manifest descriptors can carry platform metadata such as operating system and architecture. This is how one tag can support Linux/amd64, Linux/arm64, and other variants. An image manifest describes one image: a config descriptor and an ordered list of layer descriptors. A single-platform publication can resolve directly to a manifest without an index.

This difference explains a common puzzle: the digest printed for a multi-platform tag can differ from the digest of the manifest actually pulled for your host platform. Both can be correct; they name different nodes in the graph.

6. Config object, Image ID, history, and DiffIDs

The OCI config JSON contains runtime-oriented metadata such as environment, entrypoint/command fields, working directory, user, plus a rootfs structure with ordered diff_ids. A DiffID is computed over the uncompressed tar changeset, whereas a layer descriptor digest usually identifies the distributed compressed blob. Compression changes bytes, so the two digests should not be expected to match.

The config also contains history entries. Some history entries represent metadata-only build steps and have no filesystem layer. That is why “number of history rows” and “number of layer blobs” are not guaranteed to be the same.

docker image inspect busybox:1.37.0 \
  --format 'ID={{.Id}}\nRepoDigests={{json .RepoDigests}}\nRootFS={{json .RootFS}}'

7. Layers are changesets, not mini virtual disks

Each image layer describes filesystem additions, modifications, and deletions relative to the state below it. Docker combines the ordered changes to present a coherent read-only root filesystem to the container. Starting a container adds a separate writable layer; mutating that writable layer does not mutate the image.

Layer reuse is one reason content addressability matters operationally. Two local references or images can share blobs. Removing one reference therefore does not imply the shared content bytes should disappear immediately. Conversely, deleting storage directories by hand can corrupt many images at once because the store is not a folder-per-image model.

8. Local image store: inspect before assuming

Docker Engine 29 uses the containerd image store by default on fresh installations. Upgrades from older Engine versions can keep the classic graph-driver store until explicitly migrated, and userns-remap is a documented exception. The same CLI concepts—references, IDs, pulls, runs—remain useful, but disk layout and multi-platform local-storage capability can differ.

docker version
docker context show
docker info --format 'StorageDriver={{.Driver}}'
docker info | sed -n '/Storage Driver/p;/containerd image store/p'

Use the output as environment evidence. Do not teach a learner to infer the store by opening or editing /var/lib/docker; direct mutation bypasses Docker's metadata and lifecycle rules.

9. Read-only inspection sequence

Before pulling or deleting anything, establish the active context and existing local reference. Then inspect the registry-side graph and the local image separately. The following commands are observations, not cleanup commands:

SOURCE='busybox:1.37.0'

docker context show
docker version
docker image ls --digests busybox

docker buildx imagetools inspect "$SOURCE"
docker image inspect "$SOURCE" 2>/dev/null || true

If the image is absent locally, the final command failing does not contradict registry availability; it proves only that the active daemon does not currently have a matching local image object/reference.

10. DevOps use: bind release evidence to immutable identity

A strong delivery record can state: source revision X produced image index digest Y; tests/scans/attestations were evaluated for subject digest Y or a documented platform manifest; the registry accepted that content; staging and production resolved the intended digest; runtime evidence records the actual image identity. Tags can remain as convenient channels, but they should not be the only audit key.

Human navigation

Repository and tag make images discoverable.

Release identity

Digest makes exact bytes addressable and verifiable.

Platform evidence

Index → manifest proves which OS/architecture variant is intended.

Runtime handoff

Container inspection proves which image object the runtime used.

Next lesson

Next: Guided Hands-On Workflow and Core Operations

Turn the image graph into concrete evidence by pulling, inspecting, aliasing, and running one small image by the digest captured from the registry.

Knowledge check

A tag and a digest both point to an image. Why are they not equivalent release evidence?

Why can an index digest differ from the manifest digest used by your amd64 host?

Why can a manifest layer digest differ from the corresponding DiffID?

Does removing one tag necessarily delete all layer bytes it referenced?

Official references and version notes

Current baseline, not a frozen requirement

Verified 2026-09-21: Docker Engine 29.8.1 remains the current Engine 29 patch line used by this course baseline. Fresh Docker Engine 29 installations use the containerd image store by default, while upgraded older daemons can retain the classic storage-driver store; userns-remap is a documented exception. OCI Image Specification v1.1.1 is the current stable release. The mandatory lab uses the Docker Official Image busybox:1.37.0 only as a small human-readable starting reference, then captures and uses the registry-provided digest at run time. Always record the actual daemon, storage backend, platform, Buildx version, media types, and resolved digests observed on the learner's system.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.