Skip to content
Latchkey

Docker Compose "pull access denied for <image>" in CI

Compose could not pull an image one of its services references. pull access denied for <image>, repository does not exist or may require docker login means the service image is private (or misnamed) and the job has no registry authentication.

What this error means

A docker compose up/pull fails with pull access denied for myorg/internal, repository does not exist or may require 'docker login'. A docker login for that registry before the compose command fixes it.

docker
Error response from daemon: pull access denied for myorg/internal-worker,
repository does not exist or may require 'docker login': denied: requested access to the resource is denied

Diagnose it: read the resolved config, not the file you wrote

Compose merges override files, interpolates variables, and applies defaults before it does anything. Most Compose failures in CI are visible in the resolved configuration and invisible in the source file, because the value you are debugging came from an unset variable that quietly became an empty string.

Terminal
# the fully merged, interpolated configuration Compose will actually run
docker compose config

# fail loudly on unset variables instead of silently interpolating empty
docker compose --env-file .env config --quiet || echo "invalid"

# which override files were picked up
docker compose config --services

Common causes

A private service image with no login

A service image: pointing at a private repository needs docker login for that registry; without it Compose cannot pull.

A wrong image name or missing registry prefix

A typo or an image that defaults to Docker Hub when it lives on GHCR/ECR makes Compose look where the repo does not exist.

How to fix it

Log in before the compose command

Authenticate to each registry the services pull from.

.github/workflows/ci.yml
echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
docker compose pull
docker compose up -d

Use fully-qualified image references

Include the registry host in each service image.

docker-compose.yml
services:
  worker:
    image: ghcr.io/myorg/internal-worker:1.4.2

Bind mounts behave differently on a runner

  • A relative bind source is resolved against the compose file location, not the working directory of the shell that invoked it.
  • The host path must exist before up. Compose creates missing directories for named volumes but not for bind mounts, and the failure surfaces as a mount error rather than a missing-path error.
  • On a CI runner the workspace path differs from your machine, so any absolute host path in a compose file is a portability bug waiting for its first CI run.
  • Prefer named volumes for anything that does not genuinely need to be read from the host. They remove the whole class of problem.

How to prevent it

  • Log in to all service registries before docker compose pull/up.
  • Use fully-qualified image references in services.
  • Store registry tokens as CI secrets, not in the compose file.

Frequently asked questions

What causes Docker Compose "pull access denied for <image>" in CI?
There are 2 common causes: a private service image with no login and a wrong image name or missing registry prefix. A service image: pointing at a private repository needs docker login for that registry; without it Compose cannot pull.
How do I fix Docker Compose "pull access denied for <image>" in CI?
There are 2 fixes depending on which cause you have: log in before the compose command and use fully-qualified image references. Work through them in order, since the first is the most common.
What does Docker Compose "pull access denied for <image>" in CI actually mean?
A docker compose up/pull fails with pull access denied for myorg/internal, repository does not exist or may require 'docker login'.
How do I stop Docker Compose "pull access denied for <image>" in CI happening again?
Log in to all service registries before docker compose pull/up. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card