All Articles

What is a Container Registry? Docker Hub, ECR, GCR Explained (2026)

What is a container registry, why do you need one, and which one should you use? Docker Hub vs ECR vs GCR vs GitHub Container Registry — simply explained.

DevOpsBoysApr 4, 20263 min read
Share:Tweet

You've built a Docker image on your laptop. Now you need to get it running in Kubernetes on AWS. How does the image get from your machine to the cluster?

That's what a container registry solves.


What is a Container Registry?

A container registry is a storage and distribution system for Docker (container) images. Think of it like GitHub — but instead of storing code, it stores Docker images.

The flow:

Your laptop            Registry              Kubernetes
   │                      │                      │
   │  docker push image   │                      │
   │─────────────────────▶│                      │
   │                      │   docker pull image  │
   │                      │◀─────────────────────│
   │                      │                      │

Without a registry, there's no way to share images between machines, teams, or cloud environments.


How It Works

bash
# 1. Build an image on your machine
docker build -t myapp:v1.0 .
 
# 2. Tag it for a registry
docker tag myapp:v1.0 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0
 
# 3. Push to the registry
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0
 
# 4. Kubernetes pulls from the registry when deploying
# (configured in your Deployment manifest)

The Major Registries

Docker Hub

The original public registry. nginx:latest, node:18, ubuntu:22.04 — all hosted on Docker Hub.

Free tier: Public images unlimited, 1 private repo Paid plans: Unlimited private repos, team access

bash
# Pull a public image
docker pull nginx:latest
 
# Push to Docker Hub (requires account)
docker login
docker push yourusername/myapp:v1.0

Best for: Open-source projects, public images, learning

Amazon ECR (Elastic Container Registry)

AWS's managed registry. Deeply integrated with EKS, ECS, CodePipeline.

bash
# Authenticate
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin \
  123456789.dkr.ecr.us-east-1.amazonaws.com
 
# Create a repository
aws ecr create-repository --repository-name myapp
 
# Push
docker tag myapp:v1.0 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0

Best for: AWS-based workloads. Zero egress fees when pulling to EKS. IAM-based access control.

GitHub Container Registry (GHCR)

Hosted at ghcr.io. Perfect if your code is on GitHub — CI/CD builds and pushes from the same place.

bash
# Auth with GitHub token
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
 
# Push
docker tag myapp:v1.0 ghcr.io/yourorg/myapp:v1.0
docker push ghcr.io/yourorg/myapp:v1.0

Best for: GitHub Actions workflows. Public images for open-source projects.

Google Artifact Registry (GAR)

Google's registry (replaced GCR). Best for GKE workloads.

Harbor

Self-hosted, open-source registry. Includes: vulnerability scanning, image signing, replication, RBAC.

Best for: Air-gapped environments, compliance requirements, on-prem Kubernetes.


Registry Comparison

RegistryCostAuthBest For
Docker HubFree (limits)Docker loginPublic images, learning
AWS ECR$0.10/GB storedIAMAWS/EKS workloads
GHCRFree for publicGitHub tokenGitHub Actions
Google GAR$0.10/GBService accountGKE workloads
HarborSelf-hostedLDAP/OIDCOn-prem, air-gapped

In a Kubernetes Deployment

Your Deployment spec tells Kubernetes where to pull the image from:

yaml
spec:
  containers:
    - name: myapp
      image: 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.2.3
      imagePullPolicy: IfNotPresent

For private registries, Kubernetes needs credentials. On EKS with IAM roles for service accounts (IRSA) — ECR authentication is automatic. For other registries, create an imagePullSecret:

bash
kubectl create secret docker-registry regcred \
  --docker-server=ghcr.io \
  --docker-username=myuser \
  --docker-password=$GITHUB_TOKEN \
  -n my-namespace

Then reference it in your Deployment:

yaml
spec:
  imagePullSecrets:
    - name: regcred

Image Tagging Best Practices

Never use latest in production:

bash
# Bad - no way to know what version is running
image: myapp:latest
 
# Good - tied to git commit
image: myapp:a3f8c12
 
# Good - semantic version
image: myapp:v2.1.0
 
# Good - both
image: myapp:v2.1.0-a3f8c12

With latest, you can't roll back to a specific version because the tag keeps moving.


Resources

Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments