Kubernetes
K8S
Container
Image Pull Error
Local Repository

K8S Failed to pull image from local repo

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

When Kubernetes says it failed to pull an image from a "local repo," the first thing to clarify is what "local" means. From your laptop's perspective, the image might be local. From the node's perspective, it may not exist at all. Most pull failures happen because the node cannot see the image, cannot reach the registry, or is trying to pull when it should be using a locally loaded image instead.

Start with the Node's Point of View

Kubernetes pulls images from the perspective of the node that runs the pod. That means these are very different situations:

  1. The image exists only in your workstation's Docker daemon.
  2. The image exists in a registry reachable by the nodes.
  3. The image was loaded directly into the cluster runtime.

If you built an image locally on your laptop and then deployed a pod that references it, a remote cluster node cannot magically see that image. You must either push it to a reachable registry or load it into the cluster's runtime environment.

Check the Exact Error First

Before changing anything, inspect the pod events:

bash
kubectl describe pod my-pod

Look for messages such as:

  1. ErrImagePull
  2. ImagePullBackOff
  3. authentication failures
  4. "not found" for the image name or tag

Those messages tell you whether the problem is naming, registry access, or node visibility.

Use the Right Strategy for Local Clusters

For local Kubernetes distributions, there is usually a cluster-specific way to make local images available.

For kind:

bash
docker build -t my-app:dev .
kind load docker-image my-app:dev

For Minikube:

bash
docker build -t my-app:dev .
minikube image load my-app:dev

After that, reference the image directly in the pod spec and avoid forcing a remote pull if the image already exists on the node runtime.

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: my-app
5spec:
6  containers:
7    - name: my-app
8      image: my-app:dev
9      imagePullPolicy: IfNotPresent

If you use Always, Kubernetes may still try to contact a registry even when the image exists locally.

Use a Reachable Registry for Real Multi-Node Setups

If the cluster is not purely local, the more scalable solution is to push the image to a registry that every node can reach.

bash
docker build -t registry.example.com/my-team/my-app:1.0.0 .
docker push registry.example.com/my-team/my-app:1.0.0

Then use that full image reference in the manifest:

yaml
containers:
  - name: my-app
    image: registry.example.com/my-team/my-app:1.0.0

This avoids workstation-specific assumptions and makes scheduling across multiple nodes predictable.

Handle Private Registry Credentials Explicitly

If the image lives in a private registry, create an image pull secret and attach it to the pod or service account.

bash
1kubectl create secret docker-registry regcred \
2  --docker-server=registry.example.com \
3  --docker-username=my-user \
4  --docker-password=my-password \
5  --docker-email=[email protected]

Then reference it:

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: my-app
5spec:
6  imagePullSecrets:
7    - name: regcred
8  containers:
9    - name: my-app
10      image: registry.example.com/my-team/my-app:1.0.0

Without the secret, Kubernetes may reach the registry correctly but still fail the pull because the node is unauthorized.

Verify Image Name, Tag, and Pull Policy Together

These settings interact more than people expect:

  1. Wrong tag means "not found."
  2. imagePullPolicy: Always means the node keeps contacting the registry.
  3. Never means Kubernetes will fail unless the image already exists on the node.

For local testing, IfNotPresent is often the safest balance. For CI or shared clusters, explicit tags plus a real registry are usually better than relying on local cache state.

Do Not Confuse the Registry with the Runtime

A "local repo" might mean:

  1. The local Docker image cache.
  2. A registry container running on the same machine.
  3. An insecure registry reachable only on localhost.

Those are not interchangeable. If the registry is bound only to localhost, remote nodes cannot reach it. If the image is only in Docker on your laptop, the cluster runtime cannot use it unless you load or push it appropriately.

Common Pitfalls

  • Assuming an image built on the workstation is automatically visible to Kubernetes nodes.
  • Using imagePullPolicy: Always during local development and forcing unnecessary registry lookups.
  • Pushing to a private registry but forgetting the imagePullSecrets configuration.
  • Referencing the wrong image tag and then debugging networking instead of the manifest.
  • Running a "local registry" that is only reachable from localhost rather than from the nodes that need it.

Summary

  • Debug image pulls from the node's perspective, not from the workstation's perspective.
  • For local clusters, load the image into the cluster runtime or configure a reachable registry.
  • For shared or multi-node clusters, push images to a registry every node can access.
  • Use image pull secrets for private registries.
  • Check image name, tag, registry reachability, and pull policy together instead of in isolation.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.