← Articles

From Docker to Kubernetes: Pods, Nodes, and your first cluster

Published
Read
6 minutes
Part of
Kubernetes for the rest of us, ch. 01
Tags
Kubernetes · Docker · Pods · Nodes

Learn how containers, Pods, and Nodes fit together, then run your first application on a local Kubernetes cluster.

Docker gives you a container. Kubernetes gives that container somewhere to live, decides where it goes, and keeps track of what should be running. A few extra nouns come with the furniture.

The first ones to get comfortable with are Pod, Node, and cluster. I will start there, then put nginx on your laptop so you can see how they fit together. This is chapter one of eight, building toward a local setup with practices you can carry into production.

§ 01

Start with what you know

With Docker, you might run nginx like this:

terminal
docker run --rm --name guide-nginx -p 8080:80 nginx:stable

Open localhost:8080 and you should see the nginx welcome page. Docker has started a container and connected your laptop’s port 8080 to its port 80. Press Ctrl+C to stop it before continuing.

Kubernetes can run that same image. The difference starts with the Pod around it.

§ 02

A Pod is a shared flat

Think of a Pod as a flat and its containers as the people living there. They share an address and some facilities, but keep their own belongings. One tenant is perfectly normal. Several can live together when they need to share the space.

In Kubernetes terms, containers in a Pod share an IP address and can reach each other through localhost. Their filesystems stay separate, though you can configure shared volumes. Usually, you start with one application container per Pod.

A web server and a helper that updates its files could share a Pod. Your web application and database usually need separate Pods so they can scale independently. Moving a whole Compose application into one Pod would tie its components together unnecessarily.

Kubernetes schedules the whole Pod onto one Node. If you want three copies of your application, you normally create three Pods. Adding three application containers to one Pod would be rather like moving in more roommates when you wanted three separate flats.

§ 03

Nodes are the buildings

A Node supplies the CPU, memory, and container runtime that Pods need. It is usually a physical or virtual machine. In the flat analogy, it is the building: several households can live there, but each household stays in one building.

The control plane decides which Node has room for a Pod and manages the cluster’s state. Your requests reach it through the Kubernetes API. The command-line tool for sending those requests is kubectl.

ConceptWhat it does
ContainerRuns your application.
PodHolds one or more containers that run together.
NodeProvides a place for Pods to run.
ClusterCombines the control plane and the Nodes.

Control plane components and application Pods can share one Node. That makes a valid single-node cluster. Larger clusters can spread workloads across machines and separate the control plane from them. The architecture documentation covers that arrangement in more detail.

§ 04

Create your local cluster

I am using Docker Desktop’s built-in Kubernetes with its kind provisioner. It includes kubectl on Windows and macOS, so there is no separate cluster tool to install.

Install Docker Desktop for Windows or macOS. On Windows, use the WSL 2 backend with Linux containers; hardware virtualization must be enabled. If WSL is missing, run this in an administrator PowerShell window:

powershell
wsl --install

Restart if prompted, finish WSL setup, and start Docker Desktop. On macOS, choose the installer for Apple silicon or Intel. An existing Docker Desktop installation is fine if it offers the kind option.

In Docker Desktop’s Kubernetes view:

  1. Select Create cluster.
  2. Choose kind, one node, and the offered default Kubernetes version.
  3. Select Create and wait for startup to finish.

If prompted, enable the containerd image store required by this provisioner. These steps follow the UI documented in October 2026.

Here, the Node runs as a container inside Docker Desktop’s Linux environment. Even with several local Nodes, everything would still depend on the same laptop.

Open a fresh PowerShell window on Windows, or Terminal on macOS:

terminal
kubectl config use-context docker-desktop
kubectl config current-context
kubectl version
kubectl get nodes

A context selects the cluster and credentials kubectl uses. Check that the current context is docker-desktop, especially if you also use Kubernetes at work.

You should see client and server versions, followed by a Node with status Ready. Its name may vary. If kubectl is missing, reopen your terminal and check Docker Desktop’s CLI setup. If it cannot connect, check that the cluster has finished starting.

§ 05

Give nginx a Pod

Save this as nginx-pod.yaml in a working folder:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: guide-nginx
  namespace: default
spec:
  containers:
    - name: nginx
      image: nginx:stable
      ports:
        - containerPort: 80

This is a manifest: a description of the object you want Kubernetes to create. It asks for a Pod named guide-nginx, containing one container named nginx. The default namespace is an existing group for resources in the cluster.

containerPort: 80 describes nginx’s port. Unlike Docker’s -p, it does not publish anything on your laptop.

From the folder containing the file, run:

terminal
kubectl apply -f nginx-pod.yaml
kubectl wait -n default --for=condition=Ready pod/guide-nginx --timeout=120s

The first command submits the manifest. Kubernetes assigns the Pod to a Node and starts its container. The second waits for the Pod to become ready.

Inspect what was created:

terminal
kubectl get pods -n default -o wide
kubectl describe pod guide-nginx -n default

Look for guide-nginx, with 1/1 under READY and Running under STATUS. The IP and NODE columns show its address and where it lives. In describe, the Containers section lists nginx inside that Pod.

If startup stalls, check the Events section at the bottom of describe. It should tell you whether Kubernetes is struggling to download the image or find resources for the Pod.

Open nginx

For a quick look at nginx, forward a local port:

terminal
kubectl port-forward -n default pod/guide-nginx 8080:80

Leave it running and open localhost:8080. You should see the same nginx welcome page as before, now served by the container inside your Pod.

Port forwarding is a temporary connection through kubectl. Pressing Ctrl+C closes it. If 8080 is occupied, use 8081:80 and open port 8081 instead.

§ 06

What happens when the Pod disappears?

Stop port forwarding with Ctrl+C, then delete the Pod:

terminal
kubectl delete pod guide-nginx -n default
kubectl get pod guide-nginx -n default

After deletion, expect NotFound. Running the command again will show that Kubernetes has not replaced the Pod.

Kubernetes can restart a failed container inside this Pod, but deleting the Pod removes the object that asked for that container. Your YAML file is still on disk; Kubernetes does not watch it for you.

To keep an application running, something needs to maintain the requested number of Pods. A workload resource such as a Deployment gives a controller that responsibility. That is the next layer to add.

Keep the cluster and nginx-pod.yaml for the later chapters. The exercise Pod is cleaned up; you can recreate it by applying the file again.