<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniël Groothuis</title>
    <description>The latest articles on DEV Community by Daniël Groothuis (@thebighousenl).</description>
    <link>https://dev.to/thebighousenl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1213529%2F66ccc73c-66da-4c54-8573-3d83397342cd.jpeg</url>
      <title>DEV Community: Daniël Groothuis</title>
      <link>https://dev.to/thebighousenl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thebighousenl"/>
    <language>en</language>
    <item>
      <title>From Docker to Kubernetes: Pods, Nodes, and your first cluster</title>
      <dc:creator>Daniël Groothuis</dc:creator>
      <pubDate>Tue, 20 Oct 2026 18:19:36 +0000</pubDate>
      <link>https://dev.to/thebighousenl/from-docker-to-kubernetes-pods-nodes-and-your-first-cluster-b9g</link>
      <guid>https://dev.to/thebighousenl/from-docker-to-kubernetes-pods-nodes-and-your-first-cluster-b9g</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with what you know
&lt;/h2&gt;

&lt;p&gt;With Docker, you might run nginx like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; guide-nginx &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 nginx:stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;localhost:8080&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;Kubernetes can run that same image. The difference starts with the Pod around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Pod is a shared flat
&lt;/h2&gt;

&lt;p&gt;Think of a &lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/" rel="noopener noreferrer"&gt;Pod&lt;/a&gt; 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.&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nodes are the buildings
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://kubernetes.io/docs/concepts/architecture/nodes/" rel="noopener noreferrer"&gt;Node&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;kubectl&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Container&lt;/td&gt;
&lt;td&gt;Runs your application.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;Holds one or more containers that run together.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node&lt;/td&gt;
&lt;td&gt;Provides a place for Pods to run.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cluster&lt;/td&gt;
&lt;td&gt;Combines the control plane and the Nodes.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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 &lt;a href="https://kubernetes.io/docs/concepts/architecture/" rel="noopener noreferrer"&gt;architecture documentation&lt;/a&gt; covers that arrangement in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create your local cluster
&lt;/h2&gt;

&lt;p&gt;I am using Docker Desktop's built-in Kubernetes with its kind provisioner. It includes &lt;code&gt;kubectl&lt;/code&gt; on Windows and macOS, so there is no separate cluster tool to install.&lt;/p&gt;

&lt;p&gt;Install Docker Desktop for &lt;a href="https://docs.docker.com/desktop/setup/install/windows-install/" rel="noopener noreferrer"&gt;Windows&lt;/a&gt; or &lt;a href="https://docs.docker.com/desktop/setup/install/mac-install/" rel="noopener noreferrer"&gt;macOS&lt;/a&gt;. 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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--install&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;In Docker Desktop's &lt;a href="https://docs.docker.com/desktop/use-desktop/kubernetes/" rel="noopener noreferrer"&gt;Kubernetes view&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select Create cluster.&lt;/li&gt;
&lt;li&gt;Choose kind, one node, and the offered default Kubernetes version.&lt;/li&gt;
&lt;li&gt;Select Create and wait for startup to finish.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If prompted, enable the containerd image store required by this provisioner. These steps follow the UI documented in October 2026.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Open a fresh PowerShell window on Windows, or Terminal on macOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl config use-context docker-desktop
kubectl config current-context
kubectl version
kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A context selects the cluster and credentials &lt;code&gt;kubectl&lt;/code&gt; uses. Check that the current context is &lt;code&gt;docker-desktop&lt;/code&gt;, especially if you also use Kubernetes at work.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Give nginx a Pod
&lt;/h2&gt;

&lt;p&gt;Save this as &lt;code&gt;nginx-pod.yaml&lt;/code&gt; in a working folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;guide-nginx&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:stable&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;code&gt;containerPort: 80&lt;/code&gt; describes nginx's port. Unlike Docker's &lt;code&gt;-p&lt;/code&gt;, it does not publish anything on your laptop.&lt;/p&gt;

&lt;p&gt;From the folder containing the file, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; nginx-pod.yaml
kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ready pod/guide-nginx &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;120s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Inspect what was created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;-o&lt;/span&gt; wide
kubectl describe pod guide-nginx &lt;span class="nt"&gt;-n&lt;/span&gt; default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;h3&gt;
  
  
  Open nginx
&lt;/h3&gt;

&lt;p&gt;For a quick look at nginx, forward a local port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl port-forward &lt;span class="nt"&gt;-n&lt;/span&gt; default pod/guide-nginx 8080:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leave it running and open &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;localhost:8080&lt;/a&gt;. You should see the same nginx welcome page as before, now served by the container inside your Pod.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_port-forward/" rel="noopener noreferrer"&gt;Port forwarding&lt;/a&gt; is a temporary connection through &lt;code&gt;kubectl&lt;/code&gt;. Pressing Ctrl+C closes it. If 8080 is occupied, use &lt;code&gt;8081:80&lt;/code&gt; and open port 8081 instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when the Pod disappears?
&lt;/h2&gt;

&lt;p&gt;Stop port forwarding with Ctrl+C, then delete the Pod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl delete pod guide-nginx &lt;span class="nt"&gt;-n&lt;/span&gt; default
kubectl get pod guide-nginx &lt;span class="nt"&gt;-n&lt;/span&gt; default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After deletion, expect &lt;code&gt;NotFound&lt;/code&gt;. Running the command again will show that Kubernetes has not replaced the Pod.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

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

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>softwareengineering</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
