Debugging “Failed to Pull Image” Error in Minikube with Local Docker Registry: Complete Guide


4 views

When working with Minikube and local Docker registries, the "Failed to pull image" error often appears even when everything seems correctly configured. The key symptom is that while your host machine can pull the image successfully, Minikube's internal Docker daemon fails with:

rpc error: code = Unknown desc = Error response from daemon: manifest for localhost:5000/collection:dev not found

Minikube creates a separate VM (or container) with its own network stack. When you use localhost:5000 in your deployment, it refers to Minikube's localhost, not your host machine's registry.

Verify the actual registry endpoint from within Minikube:

minikube ssh
curl http://YOUR-HOST-IP:5000/v2/_catalog

Here's the correct workflow to make your local registry accessible to Minikube:

# Start Minikube with proper registry config
minikube start --insecure-registry="YOUR-HOST-IP:5000" --memory=4096

# Build and push your image (using your host IP)
docker build . -f docker.collection -t YOUR-HOST-IP:5000/collection:dev
docker push YOUR-HOST-IP:5000/collection:dev

# Update your deployment.yaml to use the host IP
image: "YOUR-HOST-IP:5000/collection:dev"

Another approach is to build images directly using Minikube's Docker daemon:

eval $(minikube docker-env)
docker build . -f docker.collection -t collection:dev

Then in your deployment.yaml:

image: "collection:dev"
imagePullPolicy: Never

When facing pull errors, these commands help diagnose the issue:

# Check kubelet logs
minikube logs | grep -i pull

# Inspect the registry contents
curl http://YOUR-HOST-IP:5000/v2/_catalog
curl http://YOUR-HOST-IP:5000/v2/collection/tags/list

# Verify image exists on registry
docker exec -it minikube curl http://YOUR-HOST-IP:5000/v2/collection/manifests/dev

Here's a verified working configuration:

# Start registry (if not running)
docker run -d -p 5000:5000 --restart=always --name registry registry:2

# Find your host IP (Linux/macOS example)
HOST_IP=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1)

# Configure Minikube
minikube start --insecure-registry="$HOST_IP:5000" --memory=4096

# Build and push
docker build . -f docker.collection -t $HOST_IP:5000/collection:dev
docker push $HOST_IP:5000/collection:dev

# Create deployment
kubectl apply -f - <

When working with Minikube and local Docker registries, the "Failed to pull image" error typically occurs due to network namespace separation between your host machine and the Minikube VM. The key symptom manifests as:

Failed to pull image "localhost:5000/collection:dev": 
rpc error: code = Unknown desc = Error response from daemon: 
manifest for localhost:5000/collection:dev not found

From your debugging attempts, we can see that while localhost:5000 resolves correctly on your host machine, Minikube's internal network sees a different localhost context. This is a common gotcha in container development.

$ minikube ssh
$ curl http://localhost:5000/v2/_catalog
# This will likely fail because the registry isn't exposed to Minikube's localhost

Solution 1: Use Minikube's Host IP

The most reliable approach is to use Minikube's special host IP instead of localhost:

# Get Minikube's host IP
$ minikube ip
192.168.49.2

# Then rebuild and push using this IP
$ docker build . -f docker.collection -t 192.168.49.2:5000/collection:dev
$ docker push 192.168.49.2:5000/collection:dev

# Update your deployment.yaml
image: "192.168.49.2:5000/collection:dev"

Solution 2: Configure Registry as Insecure

If Solution 1 doesn't work, ensure your registry is properly configured as insecure in Minikube's Docker daemon:

# Stop Minikube
$ minikube stop

# Edit Docker daemon configuration
$ minikube ssh
$ sudo vi /etc/docker/daemon.json

# Add your registry to insecure-registries
{
  "insecure-registries" : ["192.168.49.2:5000", "localhost:5000"]
}

# Restart Docker and Minikube
$ sudo systemctl restart docker
$ exit
$ minikube start

When basic solutions fail, try these diagnostic commands:

# Check kubelet logs for pull errors
$ minikube ssh
$ journalctl -u kubelet -n 50 --no-pager

# Verify image exists in registry
$ curl http://192.168.49.2:5000/v2/collection/tags/list

For production environments, consider this improved workflow script:

#!/bin/bash

# Get Minikube IP
MINIKUBE_IP=$(minikube ip)

# Build and tag
docker build . -f docker.collection \
  -t ${MINIKUBE_IP}:5000/collection:latest \
  -t ${MINIKUBE_IP}:5000/collection:dev

# Push to registry
docker push ${MINIKUBE_IP}:5000/collection --all-tags

# Apply deployment
kubectl apply -f <(sed "s/localhost:5000/${MINIKUBE_IP}:5000/g" deployment.yaml)

For complete isolation, build images directly in Minikube's Docker environment:

# Point your local Docker client to Minikube's Docker
$ eval $(minikube docker-env)

# Now build and push will work with localhost
$ docker build . -f docker.collection -t localhost:5000/collection:dev
$ docker push localhost:5000/collection:dev

# Reset Docker environment when done
$ eval $(minikube docker-env -u)