Back to Blog
Guide9 min read2026-07-09

What Is a Container Registry?

A container registry is where your Docker images live between build and deploy. This guide explains tags, digests, layers, public vs private registries, and how to secure them.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

# What Is a Container Registry?

You build a container image. Then what? It has to live somewhere your deployment targets can pull it from. That somewhere is a container registry — the package repository of the container world, like npm for Node packages or PyPI for Python, but for OCI images.

The build-store-deploy pipeline

The lifecycle of an image looks like this:

build  →  push (to registry)  →  pull (on deploy target)  →  run

The registry is the handoff point between your build system and everywhere your image needs to run — your Kubernetes cluster, a server, a teammate's laptop. Without it, the image only exists where it was built.

What's actually stored

A registry doesn't store one monolithic file per image. It stores:

  • Layers (blobs): the filesystem diffs that make up the image, content-addressed by their SHA-256 digest.
  • A manifest: JSON describing which layers and config make up an image, also content-addressed.
  • Tags: human-friendly pointers (like myapp:1.4.2) to a manifest digest.

Because layers are content-addressed, they're deduplicated. If ten images share the same Ubuntu base layer, the registry stores it once. This is also why pulls are fast when you've already got most layers cached locally.

Tags vs digests

This distinction trips up a lot of people. A tag is mutable — myapp:latest can point to a different image tomorrow. A digest is immutable — it's the cryptographic hash of the manifest, so it always refers to exactly the same bytes:

# Tag — can change
docker pull myapp:latest

# Digest — pinned forever
docker pull myapp@sha256:9b2a...c1

For reproducible, secure deployments, pin by digest in production. Tags are convenient for humans; digests are correct for machines.

Pushing and pulling

The basic flow with Docker:

# Authenticate
docker login registry.example.com

# Tag the local image with the registry path
docker tag myapp:latest registry.example.com/team/myapp:1.4.2

# Push
docker push registry.example.com/team/myapp:1.4.2

# Later, on the deploy target
docker pull registry.example.com/team/myapp:1.4.2

The full image reference is registry-host/namespace/repository:tag. Omit the host and Docker defaults to Docker Hub.

Public vs private registries

RegistryTypeNotable for
Docker HubPublic + privateDefault, huge public catalog, rate-limited pulls
GitHub Container Registry (GHCR)Public + privateTight GitHub integration
Google Artifact RegistryPrivateGCP-native, regional
Amazon ECRPrivateAWS-native, IAM auth
HarborSelf-hostedOpen source, scanning + RBAC

Docker Hub's [pull rate limits](https://docs.docker.com/docker-hub/usage/) are a real operational gotcha — unauthenticated and free-tier pulls are capped, which can break CI that pulls base images frequently. Authenticating or mirroring base images is the usual fix.

Securing a registry

A registry is a high-value target. Treat it accordingly:

  • Authentication & RBAC. Use scoped robot/service accounts for CI, not personal credentials. Grant push only where needed; most consumers only need pull.
  • Vulnerability scanning. Tools like [Trivy](https://github.com/aquasecurity/trivy) or built-in scanners flag known CVEs in image layers before they reach production.
  • Image signing. [Sigstore/cosign](https://www.sigstore.dev/) lets you cryptographically sign images and verify them at deploy time, so you only run images your pipeline actually produced.
  • Private by default. Don't expose internal images publicly. It's an easy and surprisingly common leak.
  • Lifecycle policies. Automatically prune old/untagged images so storage (and risk) doesn't grow unbounded.

A note on immutability and rollbacks

Because every pushed image is content-addressed, registries are a natural rollback mechanism. If 1.4.2 is broken, you redeploy 1.4.1 — the exact bytes are still there. This is one reason teams tag images with the Git commit SHA: every deploy is traceable to the source that produced it.

docker build -t registry.example.com/team/myapp:$(git rev-parse --short HEAD) .

How PandaStack uses a registry

When you deploy on PandaStack, builds run in rootless BuildKit pods and push the resulting image to a managed Google Artifact Registry behind the scenes. From there a Helm deploy rolls it out to multi-region GKE. You get the benefits — immutable, content-addressed images and clean rollbacks through deploy history — without provisioning, authenticating, or securing a registry yourself.

References

  • [Open Container Initiative — Distribution Spec](https://github.com/opencontainers/distribution-spec)
  • [Docker Hub usage and rate limits](https://docs.docker.com/docker-hub/usage/)
  • [Trivy vulnerability scanner](https://github.com/aquasecurity/trivy)
  • [Sigstore / cosign](https://www.sigstore.dev/)
  • [Harbor — open source registry](https://goharbor.io/)

Don't want to manage a registry, scanning, and signing yourself? PandaStack's free tier handles the whole build-store-deploy pipeline. [Start at dashboard.pandastack.io](https://dashboard.pandastack.io).

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Guide

Browse all Guide articles →

See also