k3d K3s in Docker

k3d cheatsheet — run K3s Kubernetes clusters inside Docker. k3d cluster create, k3d kubeconfig merge, k3d node add. Fast local Kubernetes for development and CI.

5 min read

k3d: K3s in Docker Cheatsheet

What it is

k3d is a tool for running K3s (a lightweight Kubernetes distribution) inside Docker containers, making it easy to spin up local Kubernetes clusters for development and testing.

Installation

Linux

curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash

macOS

brew install k3d

Windows

Download the appropriate binary from the k3d releases page and add it to your system’s PATH. Alternatively, use a package manager like Chocolatey:

choco install k3d

Core Concepts

  • Cluster: A k3d cluster is a collection of nodes (containers) running K3s.
  • Node: Each node in a k3d cluster is a Docker container. These can be server nodes (control plane) or agent nodes (workers).
  • Context: When you create a cluster, k3d automatically updates your Kubernetes configuration (~/.kube/config) to include a context for that cluster, allowing you to manage it with kubectl.

Commands / Usage

Cluster Management

Creating a Cluster

k3d cluster create mycluster

Creates a new k3s cluster named mycluster with one server node and no agent nodes.

k3d cluster create mycluster --servers 3 --agents 2

Creates a cluster named mycluster with 3 server nodes and 2 agent nodes.

k3d cluster create mycluster --k3s-arg '--disable=traefik'

Creates a cluster named mycluster and disables the default Traefik ingress controller.

k3d cluster create mycluster --registry-config k3d-registry.yaml

Creates a cluster named mycluster and configures a private Docker registry for it.

Listing Clusters

k3d cluster list

Lists all k3d clusters currently running.

Deleting a Cluster

k3d cluster delete mycluster

Deletes the cluster named mycluster.

k3d cluster delete --all

Deletes all k3d clusters.

Stopping a Cluster

k3d cluster stop mycluster

Stops the cluster named mycluster without deleting its data.

Starting a Cluster

k3d cluster start mycluster

Starts a previously stopped cluster named mycluster.

Listing Cluster Nodes

k3d node list mycluster

Lists the Docker containers (nodes) that make up the mycluster cluster.

Deleting Cluster Nodes

k3d node delete mycluster-server-0

Deletes a specific node (e.g., the first server node) from the mycluster cluster.

Accessing a Cluster’s Shell

k3d cluster exec mycluster -- /bin/sh

Opens a shell inside the first server node of the mycluster cluster.

Image Management

Loading Docker Images into a Cluster

k3d image import my-docker-image:latest -c mycluster

Loads the my-docker-image:latest from your local Docker daemon into the mycluster cluster.

k3d image import ./my-app.tar -c mycluster

Loads a Docker image saved as a tarball into the mycluster cluster.

Listing Images in a Cluster

k3d image list -c mycluster

Lists all Docker images available within the mycluster cluster.

Deleting Images from a Cluster

k3d image delete my-docker-image:latest -c mycluster

Deletes the my-docker-image:latest from the mycluster cluster.

Registry Management

Creating a Private Registry

k3d registry create myregistry --port 5000

Creates a new private Docker registry accessible on your host machine via port 5000.

Listing Registries

k3d registry list

Lists all k3d managed registries.

Deleting a Registry

k3d registry delete myregistry

Deletes the private registry named myregistry.

Configuration

Getting Cluster Configuration

k3d kubeconfig get mycluster

Prints the kubeconfig entry for the mycluster cluster.

k3d kubeconfig merge mycluster

Merges the kubeconfig for mycluster into your default ~/.kube/config.

Updating Cluster Configuration

k3d cluster update mycluster --servers 2

Updates the mycluster cluster to have 2 server nodes.

Helper Commands

Pinging a Cluster

k3d cluster ping mycluster

Checks if the mycluster cluster is responsive.

Showing Cluster Information

k3d cluster info mycluster

Displays detailed information about the mycluster cluster.

Common Patterns

Developing with kubectl

After creating a cluster (e.g., k3d cluster create dev), k3d automatically merges the cluster’s context into your ~/.kube/config. You can then use kubectl as usual:

kubectl get nodes
kubectl apply -f my-deployment.yaml

Loading a local Docker image for a deployment

Build your Docker image locally, then load it into your k3d cluster:

docker build -t myapp:latest .
k3d image import myapp:latest -c mycluster
kubectl apply -f my-deployment.yaml # The deployment uses image 'myapp:latest'

Running a multi-server HA cluster

k3d cluster create ha-cluster --servers 3 --agents 2

Using a custom Kubernetes version

k3d cluster create custom-k8s --image rancher/k3s:v1.25.7-k3s1

Mounting local directories into cluster nodes (for persistent development)

While k3d doesn’t have a direct flag for this during cluster creation, you can achieve it by manually creating a node with a bind mount. This is more advanced and often involves using docker run directly, then integrating it with k3d, or using Kubernetes PersistentVolumes with hostPath.

A simpler approach for development is to use a tool like Skaffold or Tilt which handles image building and deployment iteration.

Accessing Traefik Dashboard

If Traefik is enabled (default), you can access its dashboard:

  1. Get the Traefik service IP and port:
    kubectl get svc traefik -n kube-system -o jsonpath='{.spec.ports[?(@.name=="web")].nodePort}'
    
    (This might vary slightly depending on k3d version and Traefik configuration).
  2. Alternatively, use k3d to port-forward:
    k3d cluster exec mycluster -- /bin/sh -c 'kubectl port-forward service/traefik -n kube-system 8080:9000'
    
    Then access http://localhost:8080 in your browser.

Gotchas

  • Image Loading: Images are loaded into the runtime of the nodes, not directly into the Docker daemon of the nodes. This means docker images inside a k3d node will show the loaded images.
  • Node Restart: Stopping and starting a cluster preserves its state (pods, deployments), but restarting the underlying Docker daemon on your host might require recreating the cluster if it was not properly stopped.
  • Resource Limits: Running multiple k3d clusters or complex workloads can consume significant host resources (CPU, RAM).
  • Network Conflicts: If you run a custom registry on a port already in use on your host, k3d registry create will fail.
  • kubectl Context: Ensure your kubectl context is set to the desired k3d cluster if you have multiple Kubernetes clusters configured. Use kubectl config use-context <cluster-name>.
  • Ingress: By default, Traefik is installed. If you disable it, you’ll need to install your own ingress controller or use NodePort services for external access.
  • Docker Daemon Access: k3d relies on your host’s Docker daemon to create and manage the node containers. Ensure Docker is running and accessible.