Reading an OCI Image: Layers, Manifests, and What They Mean
Open up a container image to see its layers, manifest digest, and config — and learn why filesystem layers are content-addressed.
Netbay Infrastructure Team
Netbay Engineering
On this page
A container image is not one big file — it is a tree of metadata and filesystem layers that a pull resolves into a runnable root. If you have ever wondered why docker images shows a size that never matches the installed footprint, or why two images share storage, the answer lives in the layer model. Reading an image by hand is the fastest way to make it all concrete.
This post walks what an OCI image actually contains and how to inspect it without squinting at binary data.
The Three Pieces of an Image
An OCI image is a manifest plus a config plus a set of blobs. The manifest lists the config and the layers; the config holds JSON about environment, entrypoint, and user; each blob is a tarball of a filesystem layer, identified by a sha256 digest. The entire thing is content-addressed: layers are stored once no matter how many images reference them.
Inspecting With Standard Tools
Skip the registry web UI and read the image locally. Docker and Podman expose the manifest and config as JSON you can pipe through jq:
docker image inspect nginx:alpine | jq '.[0].Config'
docker manifest inspect nginx:alpine > manifest.json
jq -r '.config.digest, .layers[].digest' manifest.jsonThe layer digests are the same sha256 identifiers the registry stores. Each digest names a blob, and those blobs are what gets pulled when a host runs the image.
Unpacking a Layer by Hand
A layer is a gzipped tar of filesystem changes. You can pull a blob from a registry and list or extract it directly to see the classic tarball structure and the whiteout files that record deletions. This is precisely what docker export flattens for you.
# squash the whole image into one filesystem and explore it
docker export $(docker create nginx:alpine) -o rootfs.tar
tar -tvf rootfs.tar | head -20
mkdir /tmp/roots && tar -xf rootfs.tar -C /tmp/roots
find /tmp/roots/etc/nginx -maxdepth 1 | headWhy Content Addressing Matters
Because every layer is referenced by its hash, the registry and client can trust that a blob has not changed in transit — the digest is checked on pull. It also means deduplication: the ubuntu base layers you share across several images are downloaded once. And it enables immutable tags: by default a digest points to a fixed set of blobs, which is why digest-pinning deploys are reproducible.
# run a specific image version by digest, never by mutable :latest
docker pull nginx@sha256:4a2f5d9a... && docker run -d nginx@sha256:4a2f5d9a...Takeaway
Images are content-addressed manifests plus filesystem layers, and reading them with inspect and export demystifies size, caching, and sharing. That knowledge also helps you diagnose ballooning images — more on that in the image-bloat post. Start a fresh Netbay instance at netbayhosts.in, pull one of your images, and poke at its layers with the commands above.
Keep reading
Follow along on a real VPS
Deploy Linux in under 60 seconds
These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.
Deploy an instance