kind
local registry
container images
Kubernetes
DevOps

using kind to pull images from a local registry

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

KIND (Kubernetes IN Docker) runs Kubernetes clusters inside Docker containers for local development and testing. By default, KIND nodes cannot pull images from a local Docker registry because the cluster network is isolated. Configuring KIND to use a local registry lets you test custom images without pushing them to a remote registry like Docker Hub.

Prerequisites

  • Docker: Ensure Docker is installed and running on your local machine
  • kind: Install from the official GitHub repository
  • kubectl: Install to interact with your kind cluster
bash
1# Install kind
2go install sigs.k8s.io/kind@latest
3# or
4brew install kind
5
6# Verify
7kind version

Step 1: Create a Local Docker Registry

bash
# Start a local registry on port 5001
docker run -d --restart=always -p "127.0.0.1:5001:5000" --name kind-registry registry:2

Step 2: Create a KIND Cluster Connected to the Registry

Create a kind-config.yaml:

yaml
1kind: Cluster
2apiVersion: kind.x-k8s.io/v1alpha4
3containerdConfigPatches:
4- |-
5  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5001"]
6    endpoint = ["http://kind-registry:5000"]
7nodes:
8- role: control-plane

Create the cluster:

bash
kind create cluster --config kind-config.yaml

Step 3: Connect the Registry to the KIND Network

bash
# Connect the registry container to the kind network
docker network connect kind kind-registry

Step 4: Configure the Registry as a Local ConfigMap

This tells Kubernetes about the local registry:

bash
1kubectl apply -f - <<EOF
2apiVersion: v1
3kind: ConfigMap
4metadata:
5  name: local-registry-hosting
6  namespace: kube-public
7data:
8  localRegistryHosting.v1: |
9    host: "localhost:5001"
10    help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
11EOF

Step 5: Build, Tag, and Push Images

bash
1# Build your Docker image
2docker build -t my-app:latest .
3
4# Tag for the local registry
5docker tag my-app:latest localhost:5001/my-app:latest
6
7# Push to local registry
8docker push localhost:5001/my-app:latest

Step 6: Deploy Using the Local Registry Image

yaml
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: my-app
5spec:
6  replicas: 1
7  selector:
8    matchLabels:
9      app: my-app
10  template:
11    metadata:
12      labels:
13        app: my-app
14    spec:
15      containers:
16      - name: my-app
17        image: localhost:5001/my-app:latest
18        ports:
19        - containerPort: 8080
bash
kubectl apply -f deployment.yaml
kubectl get pods

Complete Setup Script

The KIND project provides an official script that automates all the steps:

bash
1#!/bin/bash
2set -o errexit
3
4# Create registry
5reg_name='kind-registry'
6reg_port='5001'
7
8if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
9  docker run -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" registry:2
10fi
11
12# Create cluster with registry config
13cat <<EOF | kind create cluster --config=-
14kind: Cluster
15apiVersion: kind.x-k8s.io/v1alpha4
16containerdConfigPatches:
17- |-
18  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"]
19    endpoint = ["http://${reg_name}:5000"]
20EOF
21
22# Connect registry to kind network
23if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
24  docker network connect "kind" "${reg_name}"
25fi
26
27# Publish registry ConfigMap
28kubectl apply -f - <<EOF
29apiVersion: v1
30kind: ConfigMap
31metadata:
32  name: local-registry-hosting
33  namespace: kube-public
34data:
35  localRegistryHosting.v1: |
36    host: "localhost:${reg_port}"
37EOF

Alternative: kind load docker-image

For one-off testing, you can load images directly into KIND nodes without a registry:

bash
1docker build -t my-app:latest .
2kind load docker-image my-app:latest
3
4# Use in pods with imagePullPolicy: Never

This is simpler but does not scale well for multiple images or CI pipelines.

Common Pitfalls

  • Network isolation: KIND nodes run in Docker containers with their own network. The registry must be on the same Docker network (kind) for nodes to reach it.
  • Image pull policy: Set imagePullPolicy: IfNotPresent or imagePullPolicy: Never for local images. The default Always tries to pull from a remote registry and fails.
  • Port mapping: The registry runs on port 5000 internally but is exposed on port 5001 to avoid conflicts. Use localhost:5001 when pushing and in pod specs.
  • Cluster recreation: If you delete and recreate the KIND cluster, reconnect the registry to the new kind Docker network.
  • containerd vs Docker: KIND uses containerd, not Docker, inside nodes. The containerdConfigPatches in the cluster config tells containerd where to find the registry.

Summary

  • Run a local Docker registry and connect it to the KIND Docker network
  • Configure KIND's containerd to mirror localhost:5001 to the registry container
  • Tag and push images to localhost:5001/image:tag
  • Reference the same image path in Kubernetes pod specs
  • For quick tests, use kind load docker-image to bypass the registry entirely

Course illustration
Course illustration

All Rights Reserved.