Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Pull Images from Private Registries

Learn how to pull Docker images from private registries with authentication, hands-on steps, and common troubleshooting tips.

Focus: pull images from private registries

Sponsored

You just built a Docker image and pushed it to a registry — but when you try docker pull my-private-image from another machine, you get a dreaded denied: requested access to the resource is denied error. Public registries are open to anyone, but real-world projects store sensitive code, proprietary binaries, or paid dependencies in private registries. Without authentication, Docker has no idea who you are and refuses to serve the image. This lesson teaches you how to pull images from private registries securely and reliably.

The problem this lesson solves

When your Docker images live in a private registry (like Docker Hub private repos, Amazon ECR, or a self-hosted Harbor instance), standard docker pull fails because the registry requires proof of identity. The error is usually:

Error response from daemon: pull access denied for mycorp/app, repository does not exist or may require 'docker login'

This blocks development, CI/CD pipelines, and deployments. You need a repeatable, automation-friendly way to authenticate and pull private images without exposing credentials in your Dockerfile or shell history.

Core concept / mental model

Think of a private registry like a gated warehouse: you can't just walk in and take a box — you need a badge that proves you have permission. Docker uses authentication tokens as that badge.

  • Registry — a server that stores Docker images (e.g., registry.example.com).
  • Repository — a named collection of images (e.g., mycorp/app).
  • Credentials — a username/password or a short-lived token.
  • docker login — the command that exchanges your credentials for an authentication token and caches it locally in ~/.docker/config.json.
  • docker pull — once authenticated, Docker includes the token in the request; the registry verifies it and streams the image layers.

Pro tip: Never store plaintext passwords in CI scripts. Use access tokens (e.g., Docker Hub personal access tokens) that you can revoke individually.

How it works step by step

  1. Choose your authentication method. Most registries support: - Username + password (basic auth) — okay for interactive use. - Personal access token (PAT) — recommended for automation, revocable. - AWS IAM / cloud provider roles — for ECR, GCR, etc.

  2. Run docker login against the registry URL.

  3. Docker stores the token in ~/.docker/config.json (base64-encoded, not encrypted).

  4. Run docker pull — Docker automatically attaches the stored token.

  5. Optional: use docker logout to clear credentials when done.

For automation (CI/CD, Kubernetes), you can pass credentials via: - stdin (secure): cat password.txt | docker login --username myuser --password-stdin - Environment variables: DOCKER_USER, DOCKER_PASS (then printed to stdin) A configuration file (avoid if possible — it's a file with secrets).

Hands-on walkthrough

Example 1: Pulling from a private Docker Hub repository

Assume you have a private repo on Docker Hub called mycompany/private-app.

# Step 1: Create a personal access token on hub.docker.com -> Account Settings -> Security
# Step 2: Log in with that token (not your account password)
docker login --username mycompanyuser --password-stdin <<< "dckr_pat_abc123def456"

# Step 3: Pull the private image
docker pull mycompany/private-app:latest

Expected output:

latest: Pulling from mycompany/private-app
Digest: sha256:abc...
Status: Downloaded newer image for mycompany/private-app:latest

Example 2: Pulling from a self-hosted registry with custom port

Many teams run their own registry (e.g., with Harbor or Docker Registry) at a custom port like 5000.

# Login
docker login registry.company.com:5000 --username deploy --password-stdin <<< "supersecret"

# Pull the image
docker pull registry.company.com:5000/team-app:1.2.3

Expected output:

1.2.3: Pulling from registry.company.com:5000/team-app
Digest: sha256:def...
Status: Image is up to date for registry.company.com:5000/team-app:1.2.3

Example 3: Using AWS ECR (IAM-based auth)

AWS ECR doesn't use docker login directly — you must run aws ecr get-login-password.

# Requires AWS CLI and IAM role with ECR permissions
aws ecr get-login-password --region us-west-2 | \
  docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-west-2.amazonaws.com

# Pull
docker pull 123456789012.dkr.ecr.us-west-2.amazonaws.com/my-app:latest

Pro tip: In CI, use the aws-actions/configure-aws-credentials action to generate IAM credentials first.

Example 4: Non-interactive login for scripts (stdin)

Never echo passwords in bash -c — use stdin redirection.

#!/bin/bash
# Safe way to pass password from a file or env var
docker login --username "$DOCKER_USER" --password-stdin < "${DOCKER_PASS_FILE}"

Or write an inline heredoc:

docker login --username robot --password-stdin << EOF
dckr_pat_abc...
EOF

Compare options / when to choose what

Method Use case Security Automation-friendly
Username + password (interactive) Quick dev test, single person Low — password cached in plaintext on disk No — requires manual typing
Personal access token (PAT) CI/CD, multiple developers High — revocable, scoped Yes — pass via stdin
AWS ECR IAM Cloud-native, AWS-only High — temporary tokens Yes — via get-login-password
OIDC / credential helpers Kubernetes, enterprise Very high — no static secrets Yes — fully automated

Troubleshooting & edge cases

Common mistakes and fixes

  • denied: requested access to the resource is denied — you didn't login, or credentials are wrong. Run docker login again with correct token.
  • Error: cannot ... — the registry URL is incorrect or the image doesn't exist. Double-check the full path including port and repository name.
  • http: server gave HTTP response to HTTPS client — you're connecting to an HTTP-only registry. For local/dev registries, add it to Docker's insecure registries list (/etc/docker/daemon.json): {"insecure-registries":["myregistry.local:5000"]}.
  • no basic auth credentials — even after login, Docker may not find the token because you logged into a different registry URL. Ensure the server in docker login matches the one in docker pull.
  • Token expiry — ECR tokens expire after 12 hours. In long-running CI pipelines, re-authenticate before pulling.

Edge cases

  • Multi-tenant registries (e.g., GitHub Container Registry): you must specify the full image name including namespace.
  • Proxied environments: set HTTP_PROXY and HTTPS_PROXY before docker login.
  • Windows: use $ | docker login with PowerShell instead of pipe.

What you learned & what's next

You now understand:

  • Why private registries require authentication (pull images from private registries starts with docker login).
  • How to authenticate interactively and non-interactively using personal access tokens or cloud IAM.
  • How to pull images from Docker Hub private repos, self-hosted registries, and AWS ECR.
  • Common pitfalls like wrong URLs, HTTP-only registries, and token expiry.

What's next: Now that you can pull private images, the next lesson covers pushing images to private registries — including tagging, versioning, and CI/CD integration. You'll apply the same authentication patterns to push (write) instead of pull (read).

Pro tip: Practice by setting up a free Docker Hub account, creating a personal access token, and pulling a private image you built earlier.

Practice recap

Set up a free Docker Hub account, create a personal access token with read scope, and pull a private image you previously pushed (or create a new one with docker tag busybox myuser/private-box && docker push). Then test pulling it from a different machine or terminal session to confirm the workflow works end-to-end.

Common mistakes

  • Using your Docker Hub account password instead of a personal access token — tokens are revocable and scoped to specific repos.
  • Forgetting to include the registry hostname/port in docker pull — a self-hosted registry on port 5000 requires registry.example.com:5000/repo:tag.
  • Hardcoding credentials in shell scripts with echo password | docker login — always use --password-stdin with < or <<< redirection to avoid exposing secrets in process lists.
  • Assuming docker login persists across user sessions in CI environments — each CI job needs its own login step, and token expiration (especially for ECR) requires re-authentication.

Variations

  1. Use a credential helper (e.g., docker-credential-ecr-login) that automatically refreshes short-lived tokens and integrates with cloud IAM.
  2. For Kubernetes, create a docker-registry secret and reference it in Pod specs — no manual docker login needed on nodes.
  3. Some registries support OIDC-based authentication (e.g., GitLab Container Registry with JWT tokens) — no static secrets exist on disk.

Real-world use cases

  • CI/CD pipeline pulls a private Docker image for unit testing, ensuring no proprietary code leaks to a public registry.
  • Production Kubernetes cluster pulls microservice images from a private Harbor registry behind a corporate firewall.
  • Developer pulls a teammate's private build artifact from a shared Docker Hub private repo for debugging integration issues.

Key takeaways

  • To pull images from private registries, you must first authenticate with docker login — never skip it.
  • Use personal access tokens instead of account passwords — they are revocable and scoped.
  • For cloud registries like AWS ECR, use IAM-based authentication via aws ecr get-login-password.
  • When automating, pass credentials via stdin (--password-stdin) to avoid secrets in logs or process lists.
  • Always confirm the full registry URL (including port) matches between docker login and docker pull.
  • Token expiry is common — re-authenticate in long-running jobs, especially with ECR (12-hour limit).

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.