OCI Image & Runtime Specs
Summary
- The Open Container Initiative (OCI) publishes three specs - image, runtime, and distribution - that let any compliant tool build, run, and share the same artifacts.
- Insight: "Docker image" is a colloquialism; the real interoperable artifact is an OCI image, which is why containerd, Podman, BuildKit, and Kubernetes all agree on it.
- Key Concepts: image manifest, config, layers, content-addressable digests, image index (multi-arch), the runtime bundle, the distribution API.
- When to Use: Any time you build, sign, scan, or move images across tools and registries and need guarantees they will interoperate.
- Limitations: The specs standardize format and lifecycle, not builder ergonomics or performance; higher-level UX still varies per tool.
Recipe
Treat OCI as the contract, and pick tools freely on either side of it.
Build with anything that emits OCI (Docker BuildKit, buildah, Kaniko), push to any registry that speaks the distribution spec, and run with any OCI runtime (runc, crun, runsc).
Pin by digest, not tag, so the content-addressable guarantee actually protects you.
Working Example
Build a standard image and inspect its OCI structure.
docker build -t registry.example.com/team/api:1.4.0 .
docker buildx imagetools inspect registry.example.com/team/api:1.4.0The output shows a manifest referencing a config blob and ordered layer blobs, each addressed by a sha256 digest.
Pull the same image with a completely different runtime to prove interoperability.
ctr images pull registry.example.com/team/api:1.4.0
podman pull registry.example.com/team/api:1.4.0Now pin by digest so the reference is immutable regardless of who repushes the tag.
containers:
- name: api
image: registry.example.com/team/api@sha256:9b2c...e41That digest is the hash of the manifest, so it uniquely and verifiably identifies exact content.
Deep Dive
The image spec
An OCI image is a manifest plus a config plus a set of layer blobs, all content-addressable.
The manifest lists the config digest and the ordered layer digests with their media types.
The config holds the runtime defaults - entrypoint, env, working dir, user, exposed ports - and the layer diff_ids and history.
Layers are gzip- or zstd-compressed tarballs; stacking them with an overlay filesystem produces the root filesystem the container sees.
Because everything is addressed by digest, identical layers are shared and deduplicated across images automatically.
Multi-arch with the image index
An image index (media type application/vnd.oci.image.index.v1+json) points to several per-platform manifests.
A single tag can therefore resolve to linux/amd64, linux/arm64, and more, and the client picks the manifest matching the node.
docker buildx build --platform linux/amd64,linux/arm64 \
-t registry.example.com/team/api:1.4.0 --push .This is how the same tag runs correctly on Graviton and x86 nodes without a separate name.
The runtime spec
The runtime spec defines a filesystem bundle: an unpacked rootfs directory plus a config.json describing how to run it.
config.json declares the process, environment, mounts, namespaces to create, cgroup limits, capabilities, and the seccomp profile.
An OCI runtime like runc reads that bundle and performs the clone, cgroup setup, pivot_root, and exec to start the container.
Higher-level runtimes translate to this: containerd unpacks an OCI image into a bundle and calls runc, which is exactly the path the kubelet drives over the CRI.
The distribution spec
The distribution spec standardizes the registry HTTP API - how clients push and pull manifests and blobs by digest and tag.
It is why docker push, ctr, oras, and cosign can all talk to Docker Hub, GHCR, ECR, or Harbor uniformly.
It also underpins storing non-image artifacts (Helm charts, SBOMs, signatures) in registries via referrers, using the same content-addressable model.
Gotchas
Tags are mutable pointers, so api:1.4.0 can be repushed to different content; pin by digest for reproducibility and supply-chain safety.
A plain manifest is single-arch, so pushing an amd64-only image and scheduling it on arm64 nodes fails with exec format error - build an index.
Not every registry implements every optional part of the distribution spec (referrers, some media types), so verify features before relying on them.
Image config sets defaults like USER and ENTRYPOINT, but Kubernetes can override them via securityContext and command, so do not assume the image config is the last word.
Layer order matters for cache and size; a poorly ordered Dockerfile busts the cache and bloats layers even though the result is still valid OCI.
Alternatives
Docker BuildKit is the default builder and emits OCI-compliant images with strong caching and multi-arch support.
buildah and Kaniko build OCI images without a Docker daemon, which suits rootless and in-cluster CI pipelines.
Podman offers a daemonless, largely Docker-compatible CLI over the same OCI artifacts and runtimes.
For non-image OCI artifacts, oras pushes and pulls SBOMs, signatures, and configs to OCI registries using the distribution spec.
Pick by workflow and security posture; the OCI contract means the artifacts remain portable across all of them.
FAQs
Is a Docker image different from an OCI image? In practice no - modern Docker builds OCI-compliant images, and the container ecosystem treats them as the same artifact.
What actually guarantees interoperability? Compliance with the OCI image, runtime, and distribution specs, which fix the format, the run contract, and the registry API.
Why pin by digest instead of tag? A digest is the content hash and is immutable, so it defends against silent repushes and makes deployments reproducible.
How does multi-arch work under one tag? An image index maps the tag to per-platform manifests, and the client selects the one matching its architecture.
Does Kubernetes use the runtime spec directly? Indirectly - the kubelet calls containerd over the CRI, and containerd invokes an OCI runtime (runc) that implements the runtime spec.
Can I store Helm charts or SBOMs in a registry? Yes - the distribution spec plus referrers lets registries hold OCI artifacts beyond images, which tools like ORAS and cosign use.
Related
- What a Container Really Is
- Container Basics
- Containers vs Virtual Machines
- Linux Namespaces & cgroups
- Container Fundamentals Best Practices
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).