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:

docker --version

You should see something like:

Docker version 24.0.2, build abc123

That means Docker is installed!

Next, run:

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 work Make sure Docker Desktop is running — look for the 🐳 icon in your top menu bar
Command not found Restart your Terminal or reboot your machine
Docker launched, but nothing’s happening The first launch can take a couple of minutes — be patient
It’s asking for permissions Check 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:

brew install kubectl

Then:

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:

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:

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.

📌 Quick 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 recognized Did the install finish cleanly? Try restarting your terminal.
minikube won’t start Is Docker Desktop running? Look for the 🐳 icon.
minikube start just hangs Try restarting Docker, rebooting, and make sure you’ve got at least 4 GB of free RAM
kubectl get nodes shows nothing Check if the cluster is running minikube status
Cluster not started Just run it again minikube 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:

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:alpine and open port 80.”

🎬 Scene 3: Apply the file and launch the Pod

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

kubectl apply -f pod.yaml

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

Then check:

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:

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 fails Cancel it (Ctrl + C) and try again kubectl port-forward pod/my-first-pod 8080:80
Port 8080 is already in use Try a different port kubectl port-forward pod/my-first-pod 8081:80 and go to localhost:8081
nginx didn’t start in the Pod Check the logs kubectl 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:

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:

kubectl apply -f deployment.yaml

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

Now check that it worked:

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:

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

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

A few seconds later:

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 nothing Make sure the file is named correctly and you’re in the right folder ls
kubectl get deployments shows nothing Could 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 logs kubectl logs <pod-name>
Don’t know the Pod name Just list all Pods kubectl get pods
error: unable to recognize Your YAML might be broken — check the format Use YAML Linter

📌 Pro tip: You can always list Pods with:

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:

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:

kubectl apply -f service.yaml

🎉 Boom — your Service is live!

Now run this:

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:

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:

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:

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:

kubectl get pods

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

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

Now run:

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 nothing Make sure you saved changes and re-applied deployment.yaml kubectl apply -f deployment.yaml
It looks right but still no variable The Pod may not have restarted — delete it manually and let Deployment recreate it kubectl delete pod <pod_name>
Can’t get into the Pod Double-check the Pod name kubectl get pods
kubectl exec doesn’t work Pod may have crashed — check status or logs kubectl 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:

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:

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:

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:

kubectl get pods

Then hop inside one:

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

Now check the variable:

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 nothing Make sure you saved and re-applied deployment.yaml kubectl apply -f deployment.yaml
Secret wasn’t created Verify it’s actually there kubectl get secrets
Pod didn’t restart Delete it manually — Deployment will recreate it kubectl delete pod <pod_name>
base64 was wrong Make sure you encoded without newline `echo -n “Hello”
Can’t enter the Pod Double-check the Pod name kubectl 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

Step What You Did Why It Matters
1 Installed Docker Runs containers — the foundation for Kubernetes
2 Installed Minikube and kubectl Local cluster and control tool
3 Created a Pod Ran your first app in Kubernetes
4 Set up a Deployment Manages and scales Pods automatically
5 Added a Service Made your app accessible from the browser
6 Connected a ConfigMap Passed env vars without rebuilding the image
7 Connected a Secret Securely 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:
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:
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:

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 want to make your digital life a little calmer — here are two tools I use every day:

🛸 Proton VPN – A trusted VPN that secures your Wi-Fi, hides your IP, and blocks trackers. Even in that no-password café Wi-Fi, you’re safe.

🔑 Proton Pass – A password manager with on-device encryption. Passwords, logins, 2FA — always with you, and only for you.

These are partner links — you won’t pay a cent more, but you’ll be supporting DevOps.Pink. Thank you — it really means a lot 💖


Tools I Personally Trust

If you want to make your digital life a little calmer — here are two tools I use every day:

🛸 Proton VPN – A trusted VPN that secures your Wi-Fi, hides your IP, and blocks trackers. Even in that no-password café Wi-Fi, you’re safe.

🔑 Proton Pass – A password manager with on-device encryption. Passwords, logins, 2FA — always with you, and only for you.

These are partner links — you won’t pay a cent more, but you’ll be supporting DevOps.Pink. Thank you — it really means a lot 💖


Refill My Coffee Supplies

💖 PayPal
🏆 Patreon
💎 GitHub
🥤 BuyMeaCoffee
🍪 Ko-fi


Follow Me

🎬 YouTube
🐦 X / Twitter
🎨 Instagram
🐘 Mastodon
🧵 Threads
🎸 Facebook
🧊 Bluesky
🎥 TikTok
💻 LinkedIn
🐈 GitHub


Is this content AI-generated?

Absolutely not! Every article is written by me, driven by a genuine passion for Docker and backed by decades of experience in IT. I do use AI tools to polish grammar and enhance clarity, but the ideas, strategies, and technical insights are entirely my own. While this might occasionally trigger AI detection tools, rest assured—the knowledge and experience behind the content are 100% real and personal.

Tatiana Mikhaleva
I’m Tatiana Mikhaleva — Docker Captain, DevOps engineer, and creator of DevOps.Pink. I help engineers build scalable cloud systems, master containers, and fall in love with automation — especially beginners and women in tech.

Tools I Personally Trust

My daily tools — tested, trusted & loved 💖

🛸 Proton VPN – secure & private connection

🔐 Proton Pass – encrypted password manager

*Partner links — you support DevOps.Pink 💕

DevOps Community

Hey hey! 💖 Need a hand with install or setup? Just give me or our awesome crew a shout: