# Docker Compose Pull Failed: Troubleshooting Image Retrieval Issues

Running docker-compose pull fails. The error could be authentication, network connectivity, registry issues, or the image simply doesn't exist. Docker Compose pulls multiple images defined in your compose file, so diagnosing which service and image is failing is the first step.

Common error messages:

bash
ERROR: for web  failed to pull image nginx:latest: pull access denied
bash
ERROR: for db  failed to pull image postgres:15: Error response from daemon: manifest for postgres:15 not found
bash
ERROR: failed to pull image: error pulling image configuration: Get https://registry-1.docker.io/v2/: dial tcp: connection refused

Quick Diagnosis

Check Which Image is Failing

bash
docker-compose config | grep image

Pull Images Individually

Isolate the problem by pulling each image separately:

bash
docker-compose config | grep image | cut -d: -f2- | while read img; do
  echo "Pulling $img..."
  docker pull "$img"
done

Check Docker Compose Logs

bash
docker-compose pull 2>&1 | tee pull-error.log

Common Causes and Fixes

Cause 1: Authentication Required

The image is from a private registry, and you're not authenticated.

Symptoms: `` ERROR: pull access denied for myregistry.com/private/app unauthorized: authentication required

Fix 1: Log in to the registry

```bash # Docker Hub docker login

# Private registry docker login myregistry.com # Enter username and password

# Using a token docker login myregistry.com -u myuser -p mytoken ```

Fix 2: Configure credentials in Docker Compose

Docker Compose uses the Docker daemon's credentials, so logging in once works for all pulls.

For CI/CD, pass credentials:

bash
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
docker-compose pull

Fix 3: Store credentials in compose file (not recommended)

yaml
# Avoid this in production - credentials visible in file
services:
  app:
    image: myregistry.com/private/app
    # No credential support in compose file directly

Instead, use environment variables:

bash
export DOCKER_REGISTRY_USER=myuser
export DOCKER_REGISTRY_PASSWORD=mypassword
docker login -u "$DOCKER_REGISTRY_USER" -p "$DOCKER_REGISTRY_PASSWORD" myregistry.com
docker-compose pull

Cause 2: Rate Limit Exceeded

Docker Hub enforces pull rate limits.

Symptoms: `` ERROR: toomanyrequests: You have reached your pull rate limit

Fix: See the rate limit article

Quick solutions:

```bash # Authenticate to increase limit docker login

# Use a mirror docker-compose pull --quiet 2>&1 | grep -v "toomanyrequests" ```

Or configure mirrors in /etc/docker/daemon.json:

json
{
  "registry-mirrors": ["https://mirror.gcr.io"]
}

Cause 3: Image or Tag Not Found

The image name or tag doesn't exist in the registry.

Symptoms: `` ERROR: manifest for myimage:v1.0 not found

Diagnosis:

```bash # Check if image exists docker search myimage

# Check available tags (Docker Hub) curl -s "https://hub.docker.com/v2/repositories/library/nginx/tags/" | jq '.results[].name'

# For private registry curl -s -H "Authorization: Bearer $TOKEN" https://myregistry.com/v2/myimage/tags/list | jq ```

Fix 1: Use correct tag

```bash # Check what tags exist docker pull myimage # Shows available tags

# Or use default tag docker pull myimage:latest ```

Update compose file:

yaml
services:
  app:
    image: myimage:correct-tag

Fix 2: Fix image name

bash
# Common mistakes
services:
  app:
    # Wrong: image: nginx  (implicitly nginx:latest from Docker Hub)
    # Correct: image: docker.io/library/nginx:latest
    # Or for private: image: myregistry.com/myorg/myimage:latest

Fix 3: Build instead of pull

If the image doesn't exist, build it:

yaml
services:
  app:
    build: ./app
    # Or
    build:
      context: ./app
      dockerfile: Dockerfile
bash
docker-compose build
docker-compose up

Cause 4: Network Connectivity Issues

Can't reach the registry.

Symptoms: `` ERROR: Get https://registry-1.docker.io/v2/: dial tcp: connection refused ERROR: net/http: request canceled while waiting for connection

Diagnosis:

```bash # Test registry connectivity curl -I https://registry-1.docker.io/v2/

# Check DNS resolution nslookup registry-1.docker.io ping registry-1.docker.io

# Check if Docker can reach internet docker run --rm alpine ping -c 3 registry-1.docker.io ```

Fix 1: Check firewall

bash
# Allow HTTPS traffic
sudo ufw allow 443/tcp
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

Fix 2: Check proxy settings

bash
# Set HTTP proxy in daemon.json
# /etc/docker/daemon.json
{
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.company.com:8080",
      "httpsProxy": "http://proxy.company.com:8080",
      "noProxy": "localhost,127.0.0.1,.internal"
    }
  }
}
bash
sudo systemctl restart docker

Fix 3: Check DNS

```bash # Add DNS servers docker-compose pull --dns 8.8.8.8

# Or configure daemon DNS # /etc/docker/daemon.json { "dns": ["8.8.8.8", "8.8.4.4"] } ```

Fix 4: VPN interference

Disconnect VPN or configure split tunneling:

bash
# Temporarily disconnect VPN
docker-compose pull

Cause 5: Private Registry TLS Issues

Private registry has certificate problems.

Symptoms: `` ERROR: Get https://myregistry.com/v2/: x509: certificate signed by unknown authority ERROR: server gave HTTP response to HTTPS client

Fix 1: Add registry as insecure

json
// /etc/docker/daemon.json
{
  "insecure-registries": ["myregistry.com:5000"]
}
bash
sudo systemctl restart docker
docker-compose pull

Fix 2: Add certificate

```bash # Get registry certificate openssl s_client -showcerts -connect myregistry.com:5000 < /dev/null 2>&1 | openssl x509 -outform PEM > myregistry.crt

# Add to Docker sudo mkdir -p /etc/docker/certs.d/myregistry.com:5000 sudo cp myregistry.crt /etc/docker/certs.d/myregistry.com:5000/ca.crt sudo systemctl restart docker ```

Fix 3: Use HTTP for local registry

yaml
services:
  app:
    image: myregistry.com:5000/myimage

Cause 6: Image Digest Mismatch

Using digest-specific pull and image changed.

Symptoms: `` ERROR: failed to pull image: content digest mismatch

Fix 1: Update digest

bash
# Get current digest
docker pull myimage:latest
docker inspect myimage:latest --format '{{index .RepoDigests 0}}'

Update compose:

yaml
services:
  app:
    image: myimage@sha256:new-digest-here

Fix 2: Use tag instead of digest

yaml
services:
  app:
    image: myimage:latest  # More flexible than digest

Cause 7: Compose File Image Specification Issues

The image reference in compose file is malformed.

Symptoms: `` ERROR: invalid reference format

Common mistakes:

```yaml # Wrong - uppercase not allowed in image names image: MyCompany/MyApp

# Correct image: mycompany/myapp

# Wrong - special characters image: my-app:v1.0-alpha # Hyphen is OK in name, but not in some contexts

# Correct image: my-app:v1.0alpha

# Wrong - missing registry for private image image: private-app

# Correct image: myregistry.com/myorg/private-app ```

Cause 8: Platform/Architecture Mismatch

The image doesn't exist for your platform.

Symptoms: `` ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries

Fix 1: Specify platform

yaml
services:
  app:
    image: nginx:latest
    platform: linux/amd64

Fix 2: Use multi-arch image

bash
# Pull with explicit platform
docker pull --platform linux/amd64 nginx:latest

Fix 3: Build for correct architecture

yaml
services:
  app:
    build:
      context: ./app
      platform: linux/amd64

Docker Compose Pull Options

Useful Pull Flags

```bash # Pull without starting docker-compose pull

# Pull specific services docker-compose pull web db

# Pull quietly docker-compose pull --quiet

# Pull with parallel downloads docker-compose pull --parallel

# Ignore pull failures (build instead) docker-compose up --ignore-pull-failures --build

# Always pull latest docker-compose up --pull always ```

Configure Pull Policy

yaml
services:
  app:
    image: nginx:latest
    pull_policy: always  # always, missing, never, build

Workaround Strategies

Use Cached Images

bash
# Pull once, cache locally
docker-compose pull
docker-compose up --no-pull

Build Instead of Pull

yaml
services:
  app:
    build:
      context: .
    # Docker Compose will build instead of pull
bash
docker-compose build --no-cache
docker-compose up

Use Local Registry

Push images to local registry first:

```bash # Pull to local registry cache docker pull nginx:latest docker tag nginx:latest localhost:5000/nginx:latest docker push localhost:5000/nginx:latest

# Reference in compose services: app: image: localhost:5000/nginx:latest ```

Verification Steps

  1. 1.Verify images pulled:
  2. 2.```bash
  3. 3.docker images
  4. 4.docker-compose images
  5. 5.`
  6. 6.Test compose up:
  7. 7.```bash
  8. 8.docker-compose up -d
  9. 9.docker-compose ps
  10. 10.`
  11. 11.Check pull logs:
  12. 12.```bash
  13. 13.docker-compose pull --quiet 2>&1
  14. 14.`
  15. 15.Verify no errors:
  16. 16.```bash
  17. 17.docker-compose config --quiet
  18. 18.`

Docker Compose pull failures are usually authentication, connectivity, or image availability issues. Pull images individually to isolate the problem, then apply the appropriate fix based on the error message.