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)