Containers and K8s
Docker, Kubernetes, service discovery.
Docker gives you reproducible runtime environments. Kubernetes adds a scheduler, service discovery, and self-healing on top. Learn Docker thoroughly before reaching for Kubernetes — most teams never need K8s, and the ones that do should know what they're paying for.
The big idea
A container packages your app and everything it needs to run into one image. That image runs identically on your laptop, in CI, and in production. Kubernetes orchestrates many containers across many machines.
Docker fundamentals
The mental model: a Linux process with its own filesystem, network namespace, and PID space — sharing the host kernel. Not a VM. Cheaper, faster, less isolated.
# Multi-stage build keeps the final image small
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]Image hygiene
- Pin versions
node:20-alpineis better thannode:latest;node:20.18.1-alpineis better still.- Multi-stage builds
- Compile in one stage, copy only the artifacts to the final stage. Drops image size 10×.
- Run as non-root
- Add a user; don't run your app as
rooteven inside a container. - `.dockerignore`
- Don't COPY your
.git,node_modules, or.env.local. - One process per container
- Trying to run nginx + your app in one container fights the model.
When to add Kubernetes
If you can answer "yes" to several of these, K8s starts paying for itself:
You have 10+ services
With deployment, scaling, and routing needs you don't want to script per-service.
You need self-healing
Crashes restart automatically; failed nodes evacuated.
You auto-scale based on load
Horizontal Pod Autoscaler keys off metrics.
You run on multiple machines
Without it, you're either over-provisioned or hand-placing containers.
If you're running 1–3 services, a single Compose file on one VM is enough. Don't adopt K8s for the resume.
Kubernetes object zoo
The handful of objects you'll touch:
- Pod
- Smallest deployable unit — one or more containers sharing an IP. Usually you don't create pods directly.
- Deployment
- Declarative recipe: "run N replicas of this pod template; if I update it, roll out gradually."
- Service
- Stable virtual IP that load-balances over the pods of a deployment. The discovery primitive.
- Ingress
- HTTP-level routing into the cluster — maps
example.com/apito a Service. Often backed by NGINX or Envoy. - ConfigMap / Secret
- Config + secrets injected as files or env vars.
- HPA
- Horizontal Pod Autoscaler — scale a deployment by CPU/memory/custom metrics.
- StatefulSet
- Pods with stable identities + persistent volumes. For databases, queues, leader-elected services.
A minimal Deployment + Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3
selector: { matchLabels: { app: api } }
template:
metadata: { labels: { app: api } }
spec:
containers:
- name: api
image: ghcr.io/example/api:1.2.3
ports: [{ containerPort: 3000 }]
readinessProbe: { httpGet: { path: /ready, port: 3000 } }
livenessProbe: { httpGet: { path: /healthz, port: 3000 } }
resources:
requests: { cpu: "100m", memory: "128Mi" }
limits: { cpu: "500m", memory: "512Mi" }
---
apiVersion: v1
kind: Service
metadata: { name: api }
spec:
selector: { app: api }
ports: [{ port: 80, targetPort: 3000 }]The non-obvious cost
K8s gives you many knobs. Each one is a chance to misconfigure something:
In practice
For a small team: Docker + Compose + a single beefy VM carries you a long way. For a team with several services and growing: managed Kubernetes (EKS, GKE, AKS) + a managed ingress and DB is the sweet spot. Self-hosted K8s on bare metal is a job description, not a side project.
Key takeaways
- A container is a process; an image is its package; pods are K8s's unit of one.
- Multi-stage Dockerfiles + pinned versions + non-root user are the basics of image hygiene.
- Reach for Kubernetes when you have many services, real auto-scaling needs, and multiple machines.
- Most apps survive happily on Compose + one VM. Don't K8s your resume.
- Set resource requests/limits from observed usage; readiness > liveness for probes.
Checkpoint questions
Use these to test whether the lesson is clear enough to explain without rereading.
- 1What problem does a container solve that a virtual machine does not solve as directly?
- 2How do image, container, pod, service, and deployment relate to each other?
- 3What should be inside a container image, and what should be provided by the environment?
- 4When is Kubernetes helpful, and when is it unnecessary complexity?
References
External resources for going deeper after the lesson above.