🚀 The Conversation That Sparked It All
Junior Developer: Hey, I keep hearing about Docker and Kubernetes everywhere. I get that they’re used for deploying apps, but what do they actually do? And how are they different?
Senior Developer: Great question. Let’s walk through it together. Think of Docker as a way to package and run a single application, and Kubernetes as the system that helps run many of those apps efficiently — especially when you're scaling.
🐳 Starting with Docker
Junior: So what happens when I run docker run
?
Senior: It starts a container — an isolated space with everything your app needs. Unlike a virtual machine, it shares the host OS kernel, so it's lightweight and fast. You use a Dockerfile
to build this image.
FROM eclipse-temurin:17-jdk
COPY target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
Then you build and run it like this:
docker build -t my-spring-app .
docker run -p 8080:8080 my-spring-app
Junior: So it's like packaging up my app and shipping it anywhere.
Senior: Exactly. That's Docker.
🔍 How Docker Works Internally
Junior: I get that Docker is fast and lightweight, but what’s really happening under the hood?
Senior: Great question. When you run a container with Docker, several things happen:
-
Docker Daemon (dockerd) takes your command (
docker run
,docker build
, etc.). - It uses Linux namespaces to isolate the container’s processes, network, and mounts.
- It applies cgroups (control groups) to limit CPU, memory, and I/O usage.
- It layers the file system with a Union File System (e.g., overlayfs), so your container filesystem is built from image layers plus any changes.
- Finally, it starts your application process inside this sandbox, which the host sees as a normal Linux process.
Junior: So it’s just a regular Linux process in a bubble?
Senior: Exactly! The host kernel manages it, but inside, it feels like a full OS.
Junior: And Docker images?
Senior: Docker images consist of multiple layers. Each instruction in your Dockerfile (RUN
, COPY
, ADD
) creates a new immutable layer. When you update an image, only changed layers are downloaded or stored, saving time and space.
☸️ Why Kubernetes?
Junior: And Kubernetes?
Senior: Docker runs one container well. But in a microservices world, you have many containers. Kubernetes helps you manage them — deploy multiple apps, scale them, expose them, roll out updates, and self-heal on failures.
Junior: So it's like a manager for Docker containers?
Senior: Perfect analogy.
🔄 How They Work Together
Docker | Kubernetes |
---|---|
Packages and runs containers | Orchestrates and scales containers |
Single-machine scope | Multi-node, distributed system |
Dev/testing tool | Production-grade orchestration |
Junior: So Kubernetes doesn't replace Docker; it uses it under the hood?
Senior: Exactly. Kubernetes can use Docker (or another container runtime) to manage container lifecycles.
🛠 Let’s Deploy a Spring Boot Microservice
Junior: Can we deploy a real app to Kubernetes?
Senior: Of course. First, build and push your Docker image:
docker build -t username/myapp:latest .
docker push username/myapp:latest
Then create two YAML files:
📄 What the YAML Files Actually Mean
Junior: We wrote deployment.yaml
and service.yaml
. Can you explain what each section does?
Senior: Sure, let’s break them down.
deployment.yaml
apiVersion: apps/v1 # Use the apps/v1 API for Deployments
kind: Deployment # This resource is a Deployment
metadata:
name: springboot-deployment # Name this deployment
spec:
replicas: 2 # Desired number of pod replicas
selector:
matchLabels:
app: springboot-app # Select pods with this label
template:
metadata:
labels:
app: springboot-app # Label applied to pods
spec:
containers:
- name: springboot-container # Container name
image: username/myapp:latest # Docker image to run
ports:
- containerPort: 8080 # Container will listen on port 8080
-
spec.replicas
: ensures two copies of the application run for availability. -
selector.matchLabels
+template.metadata.labels
: tie the Deployment to its Pods. -
containers
: defines the container image and ports for each Pod.
service.yaml
apiVersion: v1
kind: Service # This resource is a Service
metadata:
name: springboot-service # Name this service
spec:
type: NodePort # Expose on a port of each Node
selector:
app: springboot-app # Target pods with this label
ports:
- protocol: TCP
port: 80 # Port the Service listens on
targetPort: 8080 # Port on the Pod/container
nodePort: 30001 # Static port on the Node (host)
-
type: NodePort
: exposes the service onlocalhost:30001
on each node. -
selector.app
: routes traffic to Pods labeledspringboot-app
. -
port
vstargetPort
:port
is the Service port;targetPort
is the container port.
Junior: So Deployment defines the Pods, and Service exposes them.
Senior: Exactly!
🧱 Multiple Services? Bring ‘Em On
Junior: What if we have multiple microservices and a database?
Senior: Create separate Deployments and Services for each service. Add a Postgres Deployment, a corresponding Service, and optionally an Ingress resource to route external traffic based on host or path.
🧠 Final Recap
Feature | Docker | Kubernetes |
---|---|---|
Role | Build and run containers | Orchestrate containers across nodes |
Scope | Single host | Distributed cluster |
Use Cases | Dev, CI/CD, local testing | Production, autoscaling, resilience |
Key Tools | Docker CLI, Docker Compose |
kubectl , YAML manifests, Ingress |
Junior: So Docker builds; Kubernetes scales and manages.
Senior: Exactly. Together, they are the backbone of cloud-native apps.
🎯 Final Thoughts
This conversation wasn’t just a tutorial; it was a journey. You now know:
- Docker’s inner workings: namespaces, cgroups, layered filesystems
- Kubernetes basics: Deployments, Services, scaling, self-healing
- How to deploy a Spring Boot microservice step by step
- How to read Kubernetes YAML manifests
Junior: I’m ready to deploy real-world microservices!
Senior: Let’s get you production-ready.