Skip to content
ohsudo, Home
Docker & Containers

Docker "pull access denied": the repository doesn't exist, or you're not logged in

Fix Docker "pull access denied, repository does not exist or may require docker login": check the image name and tag, log in to the right registry, handle rate limits.

Beginner4 min readApplies to Docker Engine 20.10+ · Docker Compose v2 · Docker Hub · GitHub Container Registry · Amazon ECR

by OhSudo ··

Not sure this is your cause?Find it step by step: Container won't start →

Part of a learning path:Docker: from first container to production

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

Docker versions before 29 add : denied: requested access to the resource is denied.

The message offers two possibilities, because a registry won’t say whether a private image exists: “not found” and “not allowed” look alike from outside. So one of two things is true. The name is wrong, or you need to log in.

The name is the first thing to check, and here it’s the likely cause.

  1. Image nameregistry / namespace / image : tag
  2. The registrynot found, or not allowed: looks the same
  3. pull access denied(breaks here)
A registry won't say whether a private image exists, so a wrong name and a missing login give the same answer. Check the name first.

TL;DR

Terminal window
docker image ls | grep myapp # do you have it locally?
docker pull nginx:1.27 # does pulling work at all?
docker login ghcr.io # log in to the right registry
docker pull ghcr.io/acme/myapp:1.0 # with its full name

1. Read the name

An image’s full name has parts, and Docker fills in what’s missing. In ghcr.io/acme/myapp:1.0, the registry is ghcr.io, the owner is acme, the name is myapp, and the tag is 1.0.

With no registry, it means Docker Hub. With no owner, it means Docker’s official images, called library. With no tag, it means latest. So:

You wrote Docker looks for
myapp docker.io/library/myapp:latest, which is an official image called myapp
acme/myapp docker.io/acme/myapp:latest
ghcr.io/acme/myapp:1.0 Exactly that

That explains the classic case: you built myapp on one machine, and it doesn’t exist anywhere else. docker run myapp on a second machine then goes to Docker Hub, and finds nothing. Build it there, or push it to a registry and use the full name. Compare:

Terminal window
docker image ls
docker tag myapp:latest ghcr.io/acme/myapp:1.0
docker push ghcr.io/acme/myapp:1.0

In Compose, a service with only image: myapp gets pulled. Add build: ., and it’s built instead:

services:
web:
build: .
image: myapp:local

A typo gives this same error, as with ngnix for nginx. Search for the real name on the registry’s site. Check the case too, as names must be lowercase.

2. A tag that doesn’t exist

A wrong tag gives a slightly different message, and it’s worth knowing:

Error response from daemon: failed to resolve reference "docker.io/library/nginx:9.99": docker.io/library/nginx:9.99: not found

Before Docker 29, it said manifest for nginx:9.99 not found: manifest unknown. Either way, the image exists, and that version doesn’t. latest isn’t guaranteed either: an image needn’t have one. List the tags:

Terminal window
docker buildx imagetools inspect nginx:1.27

Or look on the registry’s site. For an image with versions for other CPUs, see exec format error.

3. Log in to the right registry

docker login with no name logs in to Docker Hub, and doesn’t help with other registries. Name the one you need:

Terminal window
docker login # Docker Hub
echo "$TOKEN" | docker login ghcr.io -u myuser --password-stdin
aws ecr get-login-password --region eu-central-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.eu-central-1.amazonaws.com
gcloud auth configure-docker europe-west1-docker.pkg.dev

See what you’re logged in to:

Terminal window
cat ~/.docker/config.json

sudo is a separate user. sudo docker pull uses /root/.docker/config.json, so it won’t see your login. If you only use sudo to get around a socket error, see permission denied on docker.sock instead.

Tokens. A registry often wants a token rather than your password. On GitHub, it needs the read:packages scope. ECR tokens expire after 12 hours, so a machine that logged in yesterday fails today.

4. In CI

A pipeline starts with no login, so it needs its own step, before any pull or FROM of a private image. The CI/CD Pipeline Generator writes this for GitHub Actions and GitLab CI. A private base image in a Dockerfile needs that login too, since the build pulls it.

In Compose and in a Docker Compose file, the machine running it has to be logged in. On Kubernetes, you need an imagePullSecret: see ImagePullBackOff.

5. Too many requests

If the name’s right, and you get this instead, it’s Docker Hub’s limit on anonymous pulls:

toomanyrequests: You have reached your pull rate limit.

Logging in raises it. On a busy CI server, use a pull-through mirror, or copy the images you depend on to your own registry.

6. Pushing, rather than pulling

The same wording appears when pushing:

denied: requested access to the resource is denied

Here it usually means that you’re pushing to a name you don’t own. docker push myapp means Docker’s official namespace, so tag it with your own account first: docker tag myapp myuser/myapp, then docker push myuser/myapp.

Warning

A public image is someone else’s code, running on your machine. Check a name you’ve found by searching, as look-alikes exist, and prefer official or verified publishers. Pin a version rather than latest, so that the same image runs tomorrow. And don’t put registry passwords in a Dockerfile, as they stay in the image’s layers.

Shell, we have a problem!

Similar, but different: not found after a tag, or manifest unknown on older versions, means the tag is wrong. no matching manifest for linux/arm64 means there’s no version for your CPU. Cannot connect to the Docker daemon means Docker isn’t running. x509: certificate signed by unknown authority is a proxy or a private registry’s certificate: see that article.

$ ./practice.sh

Practice this in the terminal

Open the Terminal Playground with this article’s scenario loaded. It is safe and runs in your browser.

Open the terminal →

Found this useful? Share it.

Found a mistake? Let us know at contact@ohsudo.com.

Tools

Try it yourself

Articles

Related articles