2887 words
14 minutes

Kubernetes on Your Laptop — No Cloud, No Boring Docs, Just Magic

Cover image for Kubernetes on Your Laptop — No Cloud, No Boring Docs, Just Magic

Hey there, tech goddess (or just someone who’s allergic to boring docs 👀)

You’ve probably heard of Kubernetes, but every tutorial starts with “cluster,” “orchestration,” and “in the cloud”?

😩 No thanks.

But what if I told you that you could launch your own website in Kubernetes, right on your laptop, set up environment variables, pass in secrets — step by step, no AWS, no tears, no PhD required?

Docker, Minikube, kubectl, Pod, Deployment, ConfigMap, Secret — all of it. I’ll walk you through everything.

You just open VS Code, copy a few commands — and boom: a real cluster,spinning, working, and doing your bidding like a true DevOps enchantress. Enough theory — let’s do some hands-on magic.

No AWS, no signups, no credit cards — just you, your laptop, and your curiosity. 🚀


Step 1 — Installing Docker (and figuring out why you even need it)#

Scene 1: “What even is Docker?”#

Imagine you’re trying to run an app. It works perfectly for your friend on Windows, but not for you on a Mac. She’s on Windows, you’re on a Mac. It needs a bunch of libraries you don’t have.

🎯 The fix? A container — a self-contained package that already includes everything the app needs.

🧳 A container = a suitcase with code, tools, and everything else bundled in.

Docker is the program that runs those suitcases — right on your machine.


Scene 2: “Download and install Docker”#

📝 Do this:

  1. Go to 👉 https://www.docker.com/products/docker-desktop
  2. Choose Docker Desktop for macOS (or your OS).
  3. Download the installer.
  4. Install like any other app: drag the Docker icon into your Applications folder.

📌 Once it’s installed — launch Docker Desktop (via Spotlight or Launchpad).

Quick check: is Docker working?#

🔧 Open Terminal (Cmd + Space, type “Terminal”).

Run this command:

Terminal window
bash docker --version

You should see something like:

Docker version 24.0.2, build abc123

That means Docker is installed!

Next, run:

Terminal window
docker ps

If Docker is running, you’ll see an empty table, like:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

That’s totally fine — it just means no containers are running yet.

😱 If Docker doesn’t start or docker ps throws an error:

🧨 What’s happening💡 Try this
docker ps doesn’t workMake sure Docker Desktop is running — look for the 🐳 icon in your top menu bar
Command not foundRestart your Terminal or reboot your machine
Docker launched, but nothing’s happeningThe first launch can take a couple of minutes — be patient
It’s asking for permissionsCheck if macOS is waiting for you to approve something — a pop-up might be hiding behind other windows

Why does this matter?#

We’ll be launching our Kubernetes cluster using Minikube, and Minikube runs containers under the hood.

No Docker = no cluster = no “Hello, Pod.” 😬

✅ TL;DR — You’re ready to move on if:

  • You installed Docker Desktop
  • docker --version works
  • docker ps shows an empty table (and no errors)

If all that’s good — let’s install Kubernetes (via Minikube)!


Step 2 — Installing Minikube & kubectl (and launching your first cluster!)#

Scene 1: “What are Minikube and kubectl?”#

🛠 Minikube is like a mini version of Kubernetes you can run right on your laptop.

That means: no server, no cloud, no AWS, no mystical cluster setup — Minikube spins it all up locally.

🎮 kubectl (say “cube control” or “kube cuddle”) is your remote control for that cluster.

You’ll use kubectl to create pods, check logs, update apps — basically, run the show.

Scene 2: Install kubectl and Minikube#

📝 If you’re on a Mac:

Open Terminal and run these one by one:

Terminal window
brew install kubectl

Then:

Terminal window
brew install minikube

🧘‍♀️ Take a moment, let Homebrew do its magic.

Scene 3: Start the cluster#

Once it’s installed, fire up your mini-cluster:

Terminal window
minikube start --driver=docker

💡 What’s happening here:

  • Kubernetes is starting inside Docker (which you set up in Step 1).
  • Minikube creates a “virtual machine” running your cluster.

⏱ This may take 1-2 minutes, so… deep breath.

Check if everything’s working#

Run this command:

Terminal window
kubectl get nodes

📋 You should see something like:

NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 1m v1.29.0

If you see STATUS: Ready - congrats! 🎉

Your first cluster is up. You literally just spun up your own infrastructure.

NOTE

Minikube runs a single-node cluster - perfect for learning and testing, but not meant for production. And that’s totally fine — we’re here to get hands-on, not deploy Netflix.


If something goes wrong - don’t panic!#

🔥 Problem💡 What to check🛠 Example
kubectl not recognizedDid the install finish cleanly? Try restarting your terminal.
minikube won’t startIs Docker Desktop running? Look for the 🐳 icon.
minikube start just hangsTry restarting Docker, rebooting, and make sure you’ve got at least 4 GB of free RAM
kubectl get nodes shows nothingCheck if the cluster is runningminikube status
Cluster not startedJust run it againminikube start

Why did we do this?#

  • Kubernetes is how you run and manage container-based apps.
  • Minikube lets you explore it without needing cloud servers.
  • kubectl is your command center.

Now you’re ready to create pods, deployments, services - everything a true DevOps witch needs.


Step 3 — My First Pod: Running an App in Kubernetes#

Scene 1: “What even is a Pod?”#

📦 In Kubernetes, everything revolves around Pods.

Think of a Pod as a little room with one (or more) containers inside that:

  • share network and storage
  • start together
  • live and die together

A Pod usually runs just one container (like our nginx example) - but it can have multiple, like sidecars.

Scene 2: Create a YAML file for your Pod#

📁 Open VS Code or your favorite code editor. Create a new file and name it:

Terminal window
pod.yaml

✍️ Paste this inside:

apiVersion: v1
kind: Pod
metadata:
name: my-first-pod
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80

What’s going on here:

  • apiVersion, kind, metadata — just Kubernetes boilerplate: “this is a Pod, name it like this”.
  • Inside containers: you’re saying: “Run a container using nginx and open port 80.”

Scene 3: Apply the file and launch the Pod#

In your terminal, while inside the folder with the file:

Terminal window
kubectl apply -f pod.yaml

👉 This tells Kubernetes: “Here’s the definition — go make it real!”

Then check:

Terminal window
kubectl get pods

You should see something like:

NAME READY STATUS RESTARTS AGE
my-first-pod 1/1 Running 0 10s

STATUS: Running means your Pod is alive and well! 🎉

Scene 4: Open your app in the browser#

Now let’s actually see nginx in action. Time to forward that port:

Terminal window
kubectl port-forward pod/my-first-pod 8080:80

💡 What’s this doing?

  • It tunnels port 80 from inside the container to your localhost:8080.
  • Meaning: whatever nginx serves, you can see in your browser.

Scene 5: Check if it’s working#

Pop open your browser and go to:

http://localhost:8080

If you see the default nginx page — boom, success!

If it didn’t work — deep breath, let’s fix it#

🔥 Problem💡 What to try🛠 Command
Browser says “site can’t be reached”Make sure the terminal with port-forward is still open
kubectl port-forward hangs or failsCancel it (Ctrl + C) and try againkubectl port-forward pod/my-first-pod 8080:80
Port 8080 is already in useTry a different portkubectl port-forward pod/my-first-pod 8081:80 and go to localhost:8081
nginx didn’t start in the PodCheck the logskubectl logs my-first-pod

So far, you’ve:

✅ Started your cluster
✅ Created your very first Pod
✅ Launched nginx
✅ Accessed it through the browser

This was your first real app running in Kubernetes — and that’s a huge milestone 👏👏👏


Step 4 — Deployment: So Your Pods Don’t Break (And If They Do — They Auto-Heal)#

Scene 1: “What is a Deployment, anyway?”#

In the last step, you manually created a Pod. But here’s the problem:

  • If it crashes — nobody restarts it
  • You want two Pods for reliability
  • You want Kubernetes to watch over them automatically

🎯 Enter the Deployment. It:

✅ creates Pods
✅ scales them (1, 2, 10, 100 — whatever)
✅ restarts them if they crash
✅ makes it easy to update images

Basically — a Pod manager that keeps your app alive and thriving.

Scene 2: Create the Deployment YAML#

📁 Create a new file called:

Terminal window
deployment.yaml

✍️ Paste this in:

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80

💡 What’s happening here:

  • replicas: 2 — we’re saying “Give me 2 identical Pods”
  • selector.matchLabels + template.metadata.labels — this connects the Deployment to the Pods via app: nginx
  • containers — same as before: launch nginx

Scene 3: Apply the Deployment#

Open your terminal and run this:

Terminal window
kubectl apply -f deployment.yaml

🔍 You’re telling Kubernetes: “Here’s the blueprint — build it.”

Now check that it worked:

Terminal window
kubectl get deployments

You should see something like:

NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 2/2 2 2 10s

✅ Which means: 2 Pods are up and running.

Now check the actual Pods:

Terminal window
kubectl get pods

You should see two Pods with similar names, like:

nginx-deployment-xxx-yyy 1/1 Running
nginx-deployment-aaa-bbb 1/1 Running

Scene 4: Let’s test the auto-recovery#

🧪 Tiny experiment: delete one of the Pods

Terminal window
kubectl delete pod <one-of-the-pod-names>

A few seconds later:

Terminal window
kubectl get pods

You’ll see 2 Pods again.

🤯 Because the Deployment noticed one was gone — and created a new one automatically!

If the Deployment doesn’t launch or Pods don’t appear#

🔥 Problem💡 What to check🛠 Example Command
kubectl apply -f deployment.yaml does nothingMake sure the file is named correctly and you’re in the right folderls
kubectl get deployments shows nothingCould be a YAML error (indentation, missing keys)Run kubectl apply -f deployment.yaml again to see the error
Pods crash (STATUS: CrashLoopBackOff)Something is breaking inside the container — check the logskubectl logs <pod-name>
Don’t know the Pod nameJust list all Podskubectl get pods
error: unable to recognizeYour YAML might be broken — check the formatUse YAML Linter

📌 Pro tip: You can always list Pods with:

Terminal window
kubectl get pods

Why this matters#

Now you’ve got:

  • Two Pods = more reliability
  • Self-healing containers
  • Easy updates in the future

You just leveled up from “one test container” to a real Kubernetes-managed application.


Step 5 — Service: How to Open a Pod in the Browser (Without Magic)#

Scene 1: “What is a Service?”#

You already launched 2 nginx Pods — but right now, they’re hiding behind a wall.

🙅‍♀️ Without a Service, you can’t just open them in the browser. Because:

  • Pods have internal IPs
  • They’re not accessible from “outside”
  • If a Pod restarts, its IP might change

🎯 A Service is like a stable front door to your app.

It knows where your Pods are and routes traffic to them.

Even if a Pod dies, restarts, or moves — the Service still leads to the right place.

Scene 2: Create service.yaml#

📁 Create a new file and name it:

Terminal window
service.yaml

✍️ Paste this in:

apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080

💡 What this does:

  • type: NodePort — tells Kubernetes: “Expose this to the outside world via a port”
  • selector: app: nginx — the Service will forward traffic to Pods with that label
  • port — the port the Service listens on (inside the cluster)
  • targetPort — where to send traffic inside the Pod (nginx listens on port 80)
  • nodePort — the external port you’ll use in your browser

Scene 3: Apply the Service#

In your terminal:

Terminal window
kubectl apply -f service.yaml

🎉 Boom — your Service is live!

Now run this:

Terminal window
minikube service nginx-service

🪄 That command will automatically open your site in the browser — no need to worry about ports, IPs, or voodoo.

Didn’t open? You can do it manually:

Terminal window
minikube ip

👉 You’ll get an IP, like 192.168.49.2

Now go to:

http://192.168.49.2:30080

✅ You should see the nginx welcome page!

What did we just do?#

  • You created a Service to route traffic to your Pods
  • Used NodePort to make it accessible from outside
  • Opened a real website running inside Kubernetes — without port-forward

You’re now officially at the “my app runs in K8s and opens in a browser” level —

aka your very first Kubernetes web app prototype!


Step 6 — ConfigMap: Passing Variables Into a Container (No Rebuilding Needed)#

Scene 1: “Why do we even need ConfigMap?”#

Let’s say you’ve got a website. And now you want to:

  • show a different welcome message
  • tweak the behavior without rebuilding the image
  • keep settings separate from your code

📦 ConfigMap is how you pass variables into your Pods.

Think of it like: “Here’s a YAML with your config — grab it when you start up.”

Scene 2: Create the ConfigMap#

📁 Create a file called:

Terminal window
configmap.yaml

✍️ Paste this:

apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
WELCOME_MSG: "Hello from ConfigMap!"

✨ What’s going on here:

  • data: is just a key-value map
  • WELCOME_MSG is an example string (but it could be a URL, a mode, a path — anything)

Scene 3: Update your deployment.yaml#

Open your deployment.yaml and inside the container block, add this under spec.containers[0]:

env:
- name: WELCOME_MSG
valueFrom:
configMapKeyRef:
name: nginx-config
key: WELCOME_MSG

📌 This tells Kubernetes: “When launching the container, pass it this environment variable from the ConfigMap.”

Scene 4: Apply it all#

In your terminal, run:

Terminal window
kubectl apply -f configmap.yaml
kubectl apply -f deployment.yaml

🔄 This updates both the ConfigMap and the Deployment so everything is hooked up.

Scene 5: Check if the variable is inside the container#

First, get the name of one of the Pods:

Terminal window
kubectl get pods

Copy a name (like nginx-deployment-xxx-yyy) and jump inside:

Terminal window
kubectl exec -it nginx-deployment-xxx-yyy -- /bin/sh

Now run:

Terminal window
echo $WELCOME_MSG

✅ You should see:

Hello from ConfigMap!

🎉 It worked! The variable made it all the way into your container from Kubernetes.

If the variable didn’t show up#

🔥 Problem💡 Check this🛠 Example command
echo $WELCOME_MSG shows nothingMake sure you saved changes and re-applied deployment.yamlkubectl apply -f deployment.yaml
It looks right but still no variableThe Pod may not have restarted — delete it manually and let Deployment recreate itkubectl delete pod <pod_name>
Can’t get into the PodDouble-check the Pod namekubectl get pods
kubectl exec doesn’t workPod may have crashed — check status or logskubectl get pods, kubectl logs <pod_name>

📌 Pro tip: For the new config to appear, the Pod usually has to be recreated.

kubectl apply updates the Deployment, but won’t restart running Pods.

What did you just do?#

  • Created a config variable in Kubernetes
  • Passed it into a Pod via Deployment
  • Saw the variable live inside your container

This is key when your app needs to be flexible — change config without rebuilding the Docker image.


Step 7 — Secret: Safely Passing Passwords and Tokens into a Pod#

Scene 1: “ConfigMap vs Secret — what’s the difference?”#

💡 ConfigMap — for regular settings: modes, messages, URLs.

🔐 Secret — for anything you don’t want exposed to the world:

  • passwords
  • access tokens
  • API keys

❗ Heads up: Secret values are automatically base64-encoded.

That’s not encryption — just a way to hide them from curious eyes.

Scene 2: Create a secret file#

📁 Create a new file:

Terminal window
secret.yaml

✍️ Paste this:

apiVersion: v1
kind: Secret
metadata:
name: nginx-secret
type: Opaque
data:
SECRET_MSG: SGVsbG8sIGZyb20gU2VjcmV0IQ==

✨ What’s going on:

  • type: Opaque — standard type of Secret
  • data: — key-value pairs (in base64)

📌 Example:

Terminal window
echo -n "Hello, from Secret!" | base64

Which gives you: SGVsbG8sIGZyb20gU2VjcmV0IQ==

Open your deployment.yaml.

Inside containers > env, add:

- name: SECRET_MSG
valueFrom:
secretKeyRef:
name: nginx-secret
key: SECRET_MSG

📌 Works exactly like ConfigMap — just a different data source: a Secret.

Scene 4: Apply the changes#

In your terminal:

Terminal window
kubectl apply -f secret.yaml
kubectl apply -f deployment.yaml

📦 Kubernetes will update the Secret and roll out the changes.

Scene 5: Check the container#

First, get your Pod’s name:

Terminal window
kubectl get pods

Then hop inside one:

Terminal window
kubectl exec -it <pod_name> -- /bin/sh

Now check the variable:

Terminal window
echo $SECRET_MSG

✅ You should see:

Hello, from Secret!

🎉 That means your Secret was passed into the container successfully!

If the Secret variable didn’t show up#

🔥 Problem💡 Check this🛠 Example command
echo $SECRET_MSG shows nothingMake sure you saved and re-applied deployment.yamlkubectl apply -f deployment.yaml
Secret wasn’t createdVerify it’s actually therekubectl get secrets
Pod didn’t restartDelete it manually — Deployment will recreate itkubectl delete pod <pod_name>
base64 was wrongMake sure you encoded without newline`echo -n “Hello”
Can’t enter the PodDouble-check the Pod namekubectl get pods

📌 Pro tip: If the variable doesn’t show up after apply, manually deleting the Pod usually helps.

Why does this matter?#

🔐 Secret is the standard way to safely pass sensitive data into your app — no hardcoding, no YAML leaks.

You just:

  • created a Kubernetes Secret
  • passed it into a container
  • verified it from the inside

Magic. Secure magic. 💫

⏸️ Now pause for a second.

Do you realize what you’ve just done?

You installed a cluster. Deployed an app. Passed it configs and secrets — the full DevOps starter pack.

🤯 No clouds. No five tabs of Stack Overflow. No fear of hitting Enter.

Let’s wrap it all up in a beautiful summary:


Final Recap — What You Did and Why It Matters#

StepWhat You DidWhy It Matters
1Installed DockerRuns containers — the foundation for Kubernetes
2Installed Minikube and kubectlLocal cluster and control tool
3Created a PodRan your first app in Kubernetes
4Set up a DeploymentManages and scales Pods automatically
5Added a ServiceMade your app accessible from the browser
6Connected a ConfigMapPassed env vars without rebuilding the image
7Connected a SecretSecurely passed passwords and sensitive data

✨ You just built a mini-infrastructure on your own laptop.

This isn’t just “hello world” — it’s hello Kubernetes.


So, what’s next? Two paths:#

Want to take a break and return later?#

  1. Stop the cluster:
Terminal window
minikube stop
  1. Optionally quit Docker Desktop:

    Click the 🐳 icon in the top bar → Quit Docker Desktop

🛑 That’s like hitting “pause.”

Nothing will be deleted — everything stays just as it is.

👉 When you want to come back:

  • Start Docker Desktop
  • Then run:
Terminal window
minikube start

💡 And boom — your Pods, Services, Configs, Secrets… all back in action.

Not planning to return?#

If you want to fully clean up everything we built:

Terminal window
minikube delete

This removes the cluster, all Pods, configs, and secrets — clean slate.

You can leave Docker installed — you’ll probably use it again (a lot).

Even if you never touch Kubernetes again — know this:

You started it. You understood it. You owned it. That’s already a huge step into the DevOps world.


Tools I Personally Trust#

If you’re building things, breaking things, or just trying to keep your digital life a little calmer - these are tools I actually use every day:

🛸 Proton VPN (60% off link) - my invisible cloak online. It secures your Wi-Fi, hides your IP, and blocks trackers - even on the sketchiest cafe Wi-Fi.

🔑 Proton Pass (50% off link) - my password vault. On-device encryption for logins, 2FA, and notes - all mine and only mine.

🦑 GitKraken Pro (50% off link) - my visual Git sidekick. Gorgeous commit graph, painless merges, and fewer “what just broke?” moments.

💖 These links give you sweet discounts - and help support DevOps.Pink at no extra cost. Thanks a ton!


Social Channels#

🎬 YouTube
🐦 X (Twitter)
🎨 Instagram
🐘 Mastodon
🧵 Threads
🎸 Facebook
🦋 Bluesky
🎥 TikTok
💻 LinkedIn
📣 daily.dev Squad
✈️ Telegram
🐈 GitHub


Community of IT Experts#

👾 Discord


Refill My Coffee Supplies#

💖 PayPal
🏆 Patreon
🥤 BuyMeaCoffee
🍪 Ko-fi
Telegram Boost

Kubernetes on Your Laptop — No Cloud, No Boring Docs, Just Magic
https://www.devops.pink/kubernetes-on-your-laptop-no-cloud-no-boring-docs-just-magic/
Author
Tatiana Mikhaleva
Published at
2025-05-29
License
CC BY-NC-SA 4.0