Docker Registry Storage Calculator

Work out what a registry holds. The answer is much smaller than tags times image size, and much larger than the tag count suggests after a cleanup.

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

Fifty tags of one app

Far less than fifty images, because the base is stored once

base: 120MB
app: 15MB
tags: 50

A base that dwarfs the app layer

Storage and pull time are both dominated by something identical in every tag

base: 500MB
app: 5MB
tags: 10

Common mistakes

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

  1. Estimating registry storage as tags times image size

    Layers are shared by digest, so the shared base is stored once. The estimate can be an order of magnitude too high.

    Instead:Count the base once and the changing layer per tag.

  2. Assuming deleted tags free space

    The blobs stay until garbage collection runs, which on the distribution registry needs a read-only maintenance window.

    Instead:Schedule garbage collection, and check what a managed registry's lifecycle policy actually reclaims.

  3. Putting the source COPY above the dependency install

    Every source change invalidates the install layer, so every build stores a fresh copy of all the dependencies.

    Instead:Copy the manifest files, install, then copy the source.

Layers are stored once per digest

An identical base layer is stored once however many tags reference it. So fifty builds of one application cost the base plus fifty small layers, not fifty full images.

Which is why Dockerfile order is a storage decision

Put what changes least first. A dependency install above the source COPY keeps the expensive layer shared across every build; below it, every build produces a new copy of everything.

Deleting a tag frees nothing until garbage collection runs

Deleting a manifest removes the reference and leaves every blob in place. For the CNCF distribution registry, garbage collection is a separate command that needs the registry read-only, because otherwise it can delete a blob an in-flight push is about to reference. So storage grows while the tag count falls.

Managed registries vary in what a lifecycle policy does

Some reclaim storage and some only hide tags. Worth checking rather than assuming, because the billing follows the storage rather than the tag list.

Changing the base is the expensive change

A new base is a completely new set of blobs, shared by nothing already stored, and every image built on it pulls it fresh. That is why an idle base image bump shows up as a spike in both storage and egress.

Every extra platform is another full set

An arm64 layer has a different digest from the amd64 one even for identical source, so a two-platform image is close to twice the storage, plus the attestation blobs BuildKit adds. Multi-arch is worth having and is not free.

These are compressed sizes

A registry stores the compressed blobs, which is smaller than what docker images reports, because that is the extracted size on disk. Use the compressed number for registry cost and the extracted one for node disk planning.

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 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 Manifest Viewer unknown/unknown is not broken 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