Docker Image Manifest Viewer

Read an image index or manifest. Paste-only by necessity: registry manifest endpoints send no CORS headers, so a page cannot fetch one without a server in the middle holding your credentials.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Read. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

An index with attestations

Four entries, two platforms, and the other two are supposed to be there

{
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    { "digest": "sha256:aaa", "platform": { "os": "linux", "architecture": "amd64" } },
    { "digest": "sha256:bbb", "platform": { "os": "linux", "architecture": "arm64" } },
    { "digest": "sha256:ccc", "platform": { "os": "unknown", "architecture": "unknown" } },
    { "digest": "sha256:ddd", "platform": { "os": "unknown", "architecture": "unknown" } }
  ]
}

An amd64-only image

Emulated or refused on an arm64 machine, and the failure looks like the application

{
  "manifests": [
    { "digest": "sha256:a", "platform": { "os": "linux", "architecture": "amd64" } }
  ]
}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Treating unknown/unknown entries as corruption

    They are BuildKit attestations. Time goes into investigating a registry problem that does not exist.

    Instead:Filter on the platform. Use --provenance=false if a downstream tool cannot skip them.

  2. Pinning a deployment to a per-platform digest

    It locks the deployment to one architecture, so the same manifest fails on a differently shaped node.

    Instead:Pin the index digest, which keeps the platform selection.

  3. Comparing the manifest size to docker images

    One is compressed and transferred, the other extracted and on disk. They are measuring different things.

    Instead:Use the manifest total for pull time and cost, and the extracted size for disk planning.

unknown/unknown entries are attestations, and they are supposed to be there

BuildKit records provenance and SBOM attestations as extra manifest entries with the platform set to unknown. They look like corrupt platforms and are not.

What breaks because of them

Tooling that iterates an index without filtering on the platform tries to pull them as images and fails. The count of entries is also not the count of platforms, which throws off anything checking multi-arch coverage by length. Building with --provenance=false removes them where a downstream tool cannot cope.

An index and a manifest are different documents

An index has a manifests array of per-platform entries; a manifest has a layers array. A tag points at whichever the push produced. Pinning by an index digest keeps multi-platform behaviour; pinning by a platform digest locks you to one architecture, which is occasionally what you want and usually an accident.

No arm64 entry means emulation or refusal

On Apple Silicon or an arm64 instance, Docker either declines to pull or runs the amd64 image under emulation. Emulated workloads are several times slower and some crash outright, which reads as an application bug rather than an architecture mismatch.

The sizes are compressed

Layer sizes in a manifest are the blobs as stored and transferred, which is what pull time and registry cost follow. On disk the image is larger because it is stored extracted, which is why docker images never agrees with the registry and neither number is wrong.

OCI media types are not universally accepted

buildx emits them in some configurations and a few registries, including older ECR and some appliances, only take the Docker v2 types. The push fails with a manifest error that does not mention media types.

A digest is content, a tag is a pointer

The digest is computed over the manifest bytes, so it cannot be moved. A tag can be repointed at any time by anybody who can push, which is the reason to pin by digest for anything that matters.

More docker tools

Docker Container Image Reference Parser Is that a registry or a Docker Hub user? Dockerfile Linter What this image will do to you later docker run to Kubernetes YAML And the flags that have no equivalent Docker Compose to Kubernetes And why depends_on has no equivalent Docker Logging Driver Generator json-file never rotates Dockerfile Non-Root USER Generator Numeric, or Kubernetes rejects it Docker OCI Image Labels Generator One of them actually does something Docker Hub Pull Rate Limit Calculator Counted per IP, not per person Docker Registry Storage Calculator Deleting a tag frees nothing Docker Build Context Analyzer All of it uploads before anything runs Docker Compose to docker run Converter Names stop resolving Docker Compose Version Migrator version: is obsolete now Docker Compose Network and Port Viewer Everything reaches everything Docker Command Explainer Which flags hand over the host Docker BuildKit Cache Mount Generator apt deletes the cache you just mounted Docker BuildKit Secret Mount Generator ARG is in docker history forever Docker .dockerignore Pattern Tester *.log does not match logs/app.log Docker Image Config Viewer Anyone who can pull can read your Env Docker Registry Token Decoder Check the scope before the credentials Docker HEALTHCHECK Generator Docker does nothing when it fails Docker Network Subnet Calculator 31 networks, then it stops Docker History Analyzer The rm did not save anything Docker Run to Compose Converter Some flags have no equivalent Docker CMD and ENTRYPOINT Tester Why docker stop takes ten seconds Docker Port Mapping Tester -p reaches past your firewall Docker -v to --mount Converter -v invents missing directories Docker Restart Policy Simulator The backoff resets after ten seconds Docker Exit Code Explainer 137 is two different problems Docker CPU Limit Converter --cpu-shares limits nothing Docker Memory Limit Calculator -m 512m allows a gigabyte Docker Compose Interpolation Tester An unset variable is an empty string Docker Environment Variable Precedence Tester Your shell does not reach the container Docker Compose Override Merge Previewer An override can add a port, never remove one Dockerfile Multi-Stage Build Analyzer Which stages reach the image Dockerignore Validator It is not .gitignore

Elsewhere on the site