CircleCI "unauthorized" Pulling Private Image - Fix Auth
The docker executor could not pull a private image because it sent no credentials, or the wrong ones. The registry rejects the unauthenticated pull, so the job cannot start its container.
What this error means
The job fails during "Spin up environment" / image pull with "unauthorized: authentication required" or "pull access denied". Public images work; the private one is rejected.
Error response from daemon: pull access denied for myorg/app,
repository does not exist or may require 'docker login':
denied: requested access to the resource is deniedCommon causes
No registry auth on the image
The docker: image entry has no auth: block, so CircleCI pulls anonymously and the private registry denies it.
Wrong or expired credentials
The username/token env vars are missing, misspelled, scoped wrong, or expired - common when the context holding them is not attached.
Docker Hub rate limit on anonymous pulls
Even for public images, anonymous pulls hit Docker Hub’s rate limit and return an auth-style error; authenticating raises the limit.
How to fix it
Add auth to the private image
jobs:
build:
docker:
- image: myorg/app:latest
auth:
username: $DOCKERHUB_USER
password: $DOCKERHUB_PASS
steps: [checkout, { run: ./build.sh }]Provide credentials via a context
- Store
DOCKERHUB_USER/DOCKERHUB_PASS(or a registry token) in an org context. - Attach that context to the job in the workflow.
- Use a token with read/pull scope, not a full-access password.
Authenticate to beat Hub rate limits
Even public images benefit from authenticated pulls, which lift the anonymous rate limit. This is a transient class of failure - auth makes it disappear.
How to prevent it
- Always add an
auth:block for private registry images. - Keep registry credentials in a shared context, scoped to pull.
- Authenticate Docker Hub pulls to avoid anonymous rate limits.