Lesson 24 of 30
Docker Hub is the default everyone learns on, but no real team ships private, proprietary images to a public registry — the registry itself, and how you prove you're allowed to push or pull from it, is a decision every real project has to make.
11 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
A CI pipeline needs to push images to a private registry on every merge to main. What's the strongest authentication approach?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A registry is a server that stores and serves image layers by name and tag — docker push/docker pull talk to one. Docker Hub is the default registry Docker's CLI points at if you never say otherwise, and it's genuinely fine for public, open-source images. But a real team's application images are proprietary, and Docker Hub's free tier also imposes pull-rate limits that can throttle a busy CI pipeline pulling base images all day. Almost every real deployment ends up using a private registry instead: a self-hosted one (the open-source Docker Registry image, or Harbor), or — far more commonly — the registry built into whatever cloud a team already deploys to: AWS's ECR, Google's GCR/Artifact Registry, Azure's ACR, or GitHub's GHCR (Container Registry, tied to a GitHub org).
Whichever registry a team lands on, the deciding factors are the same: who can push, who can pull, how close the registry sits to the deployment target (pulling from ECR into an ECS task in the same AWS region is faster and doesn't cross the public internet), and whether it integrates with the cloud's existing IAM rather than needing a separate credential system.
# Docker Hub or a self-hosted registry — username + password/token
docker login registry.example.com
# AWS ECR — no long-lived password; exchange an IAM identity for a short-lived token
aws ecr get-login-password --region us-east-1 \
| docker login --username AWS --password-stdin \
123456789012.dkr.ecr.us-east-1.amazonaws.com
docker login doesn't just authenticate one command — it writes credentials to ~/.docker/config.json (or hands them to a credential helper) so every subsequent docker push/docker pull against that registry is already authenticated. That persistence is exactly why the kind of credential stored there matters: a personal Docker Hub password sitting in that file on a laptop is a very different risk than a token that expires in twelve hours.
get-login-password expires in hours; this is a deliberate tradeoff (a compromised CI log leaking that token is a much smaller window of exposure than a leaked long-lived password) and pipelines are expected to re-fetch one per run, not cache it.docker login's stored credential is only as safe as the machine it's on. Without a credential helper (docker-credential-desktop, docker-credential-ecr-login, etc.), Docker falls back to storing the auth token in ~/.docker/config.json in a lightly-obscured but not encrypted form — a credential helper backed by the OS keychain is the safer default on a real workstation.node:20-alpine from Docker Hub on every run can get throttled once anonymous or free-tier pull limits are hit — mirroring commonly-used base images into a private registry the team controls is a common fix, not just a private-image concern."How does your CI pipeline authenticate to push images without a developer's personal credentials sitting in a config file?" is a real, senior-leaning question, and naming the specific mechanism — a scoped machine identity or IAM-role-based short-lived token, not a shared password — is what separates an answer that's actually been through a security review from one that hasn't.