“Docker takes your app and builds it into a container image. Kubernetes then runs it in production.”
Table of Contents
- Overview
- Module 1 — Core Concepts
- Module 2 — Docker and Containers
- Module 3 — Kubernetes and Orchestration
- Module 4 — GitOps Workflows
- Architecture Diagrams
- Code Snippets
- Reference Tables
- Key Concepts to Remember
1. Overview
Docker and Kubernetes form the central duo of modern application infrastructure. They are often described as “build and runtime cousins”:
| Tool | Primary role |
|---|---|
| Docker | Builds container images and runs containers locally |
| Kubernetes | Orchestrates containers in production at scale |
The course instructor (author of the first book ever written on Kubernetes and one of the first on Docker) notes that even with extensive command experience, it took time to grasp the fundamental principles that unlock the full power of these technologies. This course fills exactly those gaps.
What this course covers:
- Shared kernel architecture and VM isolation
- Microservices design patterns
- Immutability concept for images
- CI/CD pipelines and GitOps workflows
- Standards and specifications: OCI, CNCF, Moby
2. Module 1 — Core Concepts
The Problem Solved: “It works on my machine”
Before containers, the number one problem in application deployment was the infamous phrase “it worked on my machine”. The root cause: library files and config files shared between applications on the same server.
Classic scenario without containers:
Server
├── App 1 ──────┐
│ ├── shared_lib v1.2 ← App 2 updates → shared_lib v2.0 → App 1 BREAKS
└── App 2 ──────┘
The Docker solution:
Each container image bundles everything the application needs:
- Application code
- Libraries and dependencies
- Configuration files
- Complete filesystem
Container Image
├── /app/ ← your code
├── /usr/lib/ ← libraries specific to this version
├── /etc/ ← configuration
└── ... ← everything else
Thus, regardless of the execution environment (dev, test, prod), the image is identical everywhere. The “it worked on my machine” problem is eliminated structurally.
Container Architecture: Shared Kernels vs VM Isolation
Typical container stack
┌─────────────────────────────────────┐
│ App 1 │ App 2 │ App 3 │ ... │ ← Applications
├─────────┴─────────┴─────────┴───────┤
│ Container Runtime │ ← containerd + runc
├──────────────────────────────────────┤
│ Linux OS │ ← Shared kernel
├──────────────────────────────────────┤
│ Hardware / Cloud │
└──────────────────────────────────────┘
Shared Kernels Model (dominant)
All containers on the same host share the host’s kernel. Each container gets:
- Its own process tree with a
PID1 - Its own shared memory
- Its own network stack (interfaces, routing tables, firewall rules)
- Its own filesystem (via union mounts)
Advantages: Fast, resource-efficient
Risk: If a container compromises the kernel, all containers are at risk
VM Isolation Model (enhanced security)
Each container runs in its own lightweight micro-VM. No kernel sharing.
Advantages: Strong isolation, maximum security
Disadvantages: Slower, consumes more resources
Good news: No workflow change — works with standard OCI images
VMs vs Containers Comparison
| Criterion | Traditional VMs | Docker Containers |
|---|---|---|
| Size | Several GB | A few MB to 100s MB |
| Startup | Minutes | Seconds |
| Isolation | Full kernel per VM | Shared kernel |
| Overhead | High (hypervisor) | Minimal |
| Portability | Limited | Excellent (OCI) |
| Density | Low | Very high |
Linux vs Windows vs Mac
Reality: ~99.9999% of containers are Linux containers.
| Platform | Situation |
|---|---|
| Linux | Native containers, direct kernel |
| Windows | Windows containers exist but very rare; Linux containers via WSL2 (hidden VM) |
| Mac | Linux containers via hidden lightweight Linux VM |
Workflow on Windows/Mac: Code is written normally, then Docker runs everything in a transparent Linux VM. The resulting image is identical to one produced on Linux — compatible with Kubernetes and the entire ecosystem.
The Microservices Revolution
Before: Monolithic Applications
Monolithic Application
┌──────────────────────────────────────────┐
│ User interface │
│ + Database │
│ + User management │
│ + Reporting middleware │
│ + Business logic module │
│ + ...everything else... │
└──────────────────────────────────────────┘
↓ Update = entire weekend
Problems with monoliths:
- Updated once a year, planned 6 months in advance
- Requires the entire team: networking, storage, DBAs, Linux admins, application vendor
- Full weekend of work under maximum pressure
- Everything is coupled — modifying reporting risks breaking the database
After: Microservices Architecture with Docker
Microservice 1 Microservice 2 Microservice 3 Microservice 4
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Interface │ │ User Mgmt │ │ Reporting │ │ Compute │
│ (React) │ │ (Node.js) │ │ (Python) │ │ (Java) │
│ │ │ │ │ │ │ │
│ Container 1 │ │ Container 2 │ │ Container 3 │ │ Container 4 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
Advantages:
- Independent updates for each service
- Dedicated team per service
- Granular horizontal scaling
- Zero-downtime deployments (rolling updates)
- Each service exposes a well-defined REST API
The Need for Orchestration
The downside of microservices: container sprawl (container proliferation).
| Before (monolith) | After (microservices) |
|---|---|
| 1 app = 2 VMs (HA) | 1 app = 20 to 30+ containers |
| Simple to manage | Requires an orchestrator |
Kubernetes is the dominant orchestrator. Its role:
- Scheduling: place containers on the right nodes
- Self-healing: restart failing containers, replace dead nodes
- Scaling: automatically increase/decrease replica count
- Rolling updates: deploy without service interruption
- Load balancing: distribute traffic across replicas
- Service discovery: allow services to find each other
Course analogy: Kubernetes is the coach of a soccer team — it organizes players (containers), replaces them if injured (self-healing), and adapts strategy mid-game (dynamic scaling).
Standards and Specifications: OCI, CNCF, Moby
These standards are the foundation of trust in the container ecosystem. Course analogy: Like the standardization of railroad gauges in the 19th century catalyzed global railway innovation, OCI specs catalyze container innovation.
OCI — Open Container Initiative
Vendor-neutral standard defining three specifications:
| OCI Spec | What it standardizes |
|---|---|
| Image Spec | Structure and format of container images |
| Distribution Spec | How to store and retrieve images in registries |
| Runtime Spec | How to execute an image as a container |
CNCF — Cloud Native Computing Foundation
- Governance and development of Kubernetes and many cloud-native projects
- Members: Google, Amazon, Microsoft, IBM, Red Hat, etc.
- Ensures ecosystem neutrality and longevity
Moby Project
- Open-source infrastructure underlying Docker
- Modular components reused throughout the industry
Practical importance: Choosing tools that respect these standards guarantees interoperability and protects your investments long-term.
High-Level Workflow
Simplified workflow
Code → docker build → docker push → Kubernetes run
Real workflow with CI/CD and GitOps
1. Developer commits code → Git repo (app code)
2. CI tool detects the commit
3. CI: docker build (image)
4. CI: docker push (registry)
5. CI: run automated tests
6. CI: updates config repo (production YAML)
7. GitOps tool detects change in config repo
8. GitOps: kubectl apply on Kubernetes cluster
9. Production updated automatically
Everything is automatic and pull-based after the developer’s commit. That’s the magic of GitOps.
3. Module 2 — Docker and Containers
Docker History
2008: Solomon Hykes and associates found dotCloud, a PaaS company that uses Linux containers (not VMs) under the hood. Linux containers existed, but were difficult to use.
Internal solution: To simplify their own work, they create an internal tool — initially called “DC” — that would become Docker.
March 2013: Solomon Hykes presents Docker in 5 minutes at PyCon in Santa Clara. “Hello World” demo in front of the entire world. Instant revolution.
Evolution:
- Early days: Docker Inc. controlled everything (monolithic daemon)
- Rapid growth but governance issues
- Contribution to open-source projects: containerd (CNCF), runc (OCI)
- Today: modular architecture, community-governed components
Docker Inc. (big D) vs docker (little d):
- Docker Inc. = the company in Palo Alto, California
- docker = the technology that builds images and runs containers
Docker Architecture
┌─────────────────────────────────────────────────────────┐
│ Docker Client (CLI) │
│ $ docker build / push / run │
└──────────────────────┬──────────────────────────────────┘
│ API calls (REST)
┌──────────────────────▼──────────────────────────────────┐
│ Docker Daemon │
│ (long-running daemon process) │
│ ┌───────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ BuildKit │ │ containerd │ │ libnetwork │ │
│ │ (builds) │ │ (lifecycle) │ │ (networking) │ │
│ └───────────┘ └──────┬───────┘ └──────────────────┘ │
│ │ │
│ ┌─────▼──────┐ │
│ │ runc │ │
│ │(OCI runtime│ │
│ │ spec) │ │
│ └────────────┘ │
└─────────────────────────────────────────────────────────┘
Key components:
| Component | Role |
|---|---|
| Docker CLI | User interface, converts commands to API calls |
| Docker Daemon | Server, exposes REST API, delegates to specialized components |
| BuildKit | Image build engine (replaces legacy builder) |
| containerd | Manages container lifecycle (start, stop, pause…) |
| runc | Low-level runtime, creates containers per OCI spec |
| libnetwork | Container network management |
Client-server architecture: The client and server can run on different machines, but in practice they are on the same machine (including in the hidden Linux VM on Windows/Mac).
Docker Demo: Build, Push, Run
# Build an image from the Dockerfile
docker build -t myapp:v1.0 .
# Push to Docker Hub (upload)
docker push myaccount/myapp:v1.0
# Pull and run from any machine (download + execute)
docker run -d -p 8080:80 myaccount/myapp:v1.0
# Check running containers
docker ps
# View logs
docker logs <container_id>
What happens under the hood during docker build:
- The CLI sends the build context to the daemon via the API
- The daemon delegates to BuildKit
- BuildKit reads the Dockerfile instruction by instruction
- Each instruction creates a layer in the image
- The final image is a stack of layers (union filesystem)
- The image is OCI-compliant — portable everywhere
4. Module 3 — Kubernetes and Orchestration
Kubernetes History
Before Kubernetes at Google: Google processed billions of containers per week for Search, Gmail and other services, before Docker even existed. They used internal tools: Borg and Omega.
2014: Google engineers draw inspiration from Borg/Omega to create a new tool from scratch, developed open-source on GitHub. It is neither a port nor a rename — it is an original creation.
Anecdote: They wanted to call it Seven of Nine (a Borg drone from Star Trek — a nod to Borg, Google’s internal tool + Borg from Star Trek). Copyright law prevailed. They settled on Kubernetes, from ancient Greek kybernḗtēs = “helmsman”. Hence the logo with the ship’s wheel.
k8s: Official abbreviation — “K” + 8 letters + “s”. Popular contraction of “Kubernetes”.
Governance: Kubernetes is now under the umbrella of CNCF (Cloud Native Computing Foundation), ensuring vendor neutrality and longevity.
Kubernetes: The Cloud OS
The analogy is powerful: Kubernetes does for clouds what an OS does for hardware.
Traditional OS: Kubernetes:
┌────────────────────┐ ┌────────────────────────┐
│ Applications │ │ Your apps (containers)│
├────────────────────┤ ├────────────────────────┤
│ Linux / Windows │ │ Kubernetes │
│ (abstracts HW) │ │ (abstracts the cloud) │
├────────────────────┤ ├────────────────────────┤
│ CPU / RAM / Disk │ │ AWS / Azure / GCP / │
│ (doesn't matter │ │ On-premises / Home lab │
│ which) │ │ (doesn't matter) │
└────────────────────┘ └────────────────────────┘
Practical consequences:
- Migrating from AWS to Azure? Kubernetes abstracts the differences
- Bursting to the cloud from on-premises? Kubernetes handles it
- Multi-cloud? Kubernetes unifies the interface
- No magic — there are always considerations — but the abstraction makes everything much simpler
The Declarative Model
Imperative (scripts): “Do X, then Y, then Z…”
Declarative (Kubernetes): “Here’s what I want. Figure it out.”
Course analogy: Telling your architect “I want an open-plan kitchen connected to the living room, with glass doors on the garden side and a level floor with the terrace” — that’s declarative. You declare the desired state and let the expert handle the details.
How it works:
1. You write a YAML file (desired state)
2. kubectl apply -f deployment.yaml
3. Kubernetes compares desired state vs current state
4. Kubernetes executes actions to reach desired state
5. Kubernetes continuously monitors and maintains desired state
Control loop:
┌─────────────────────────────────┐
│ Kubernetes │
│ │
Desired │ ┌──────────────────────────┐ │
State │ │ Observe current state │ │
(YAML)──►│ │ Compare with desired │ │
│ │ Take corrective action │ │
│ └──────────────────────────┘ │
│ ↕ (infinite loop) │
└─────────────────────────────────┘
Kubernetes Demo: Deployment and Self-Healing
Cluster used in the demo: 1 control plane node + 3 worker nodes (4 nodes total)
# Apply declarative configuration
kubectl apply -f deployment.yaml
# View deployed pods
kubectl get pods
# See which nodes the pods are running on
kubectl get pods -o wide
# Scale manually
kubectl scale deployment myapp --replicas=6
# View deployments
kubectl get deployments
# Describe a deployment for details
kubectl describe deployment myapp
# View nodes
kubectl get nodes
Self-healing in action:
# Simulate a node failure
kubectl cordon node3 # mark node as non-schedulable
kubectl drain node3 # evacuate pods to other nodes
# Kubernetes automatically redeploys pods to remaining nodes
kubectl get pods -w # -w = watch (real-time)
Result with 4 replicas on 3 nodes: Kubernetes automatically distributes — one node receives 2 containers. When a node fails, containers are automatically rescheduled on available nodes.
5. Module 4 — GitOps Workflows
Complete Workflow Summary
This module recaps the entire Docker → Kubernetes pipeline in a real context and introduces GitOps as the standard pattern in production.
OCI Specs Recap
| Spec | Function |
|---|---|
| Image Spec | Standardizes container image structure |
| Distribution Spec | Standardizes storage/retrieval in registries |
| Runtime Spec | Standardizes container execution |
These three specs guarantee that Docker images work on Kubernetes (and vice-versa) without modification.
GitOps — Modern Deployment Pattern
Fundamental principle: Git is the single source of truth for everything — both application code AND infrastructure configuration.
Two Git repos:
- App repo: application source code
- Config repo: production Kubernetes YAML files
Popular GitOps tools: ArgoCD, Flux
Developer
│ git commit + push
▼
App Git Repo ──────────────────────────────►
│ │
│ (CI tool observes) │
▼ │
CI Pipeline (GitHub Actions, Jenkins...) │
│ docker build │
│ docker push → Registry │
│ update config repo (new image tag) │
▼ │
Config Git Repo ◄────────────────────────────
│
│ (GitOps tool observes)
▼
GitOps Tool (ArgoCD/Flux) on Kubernetes
│ kubectl apply (automatic)
▼
Production Kubernetes Cluster ✓
GitOps advantages:
- Full auditability: every deployment is a traceable Git commit
- Easy rollback:
git revert= deployment rollback - No direct access to production cluster (principle of least privilege)
- Consistency: cluster state always reflects Git
- Pull-based: cluster pulls config from Git (vs push-based)
6. Architecture Diagrams
Docker + Kubernetes Architecture
graph TB
subgraph "Developer Machine"
DEV[Source Code]
DF[Dockerfile]
DC[docker-compose.yml]
end
subgraph "Docker Build Pipeline"
BK[BuildKit]
IMG[Container Image OCI]
end
subgraph "Registry"
DH[Docker Hub]
ECR[AWS ECR]
ACR[Azure ACR]
end
subgraph "Kubernetes Cluster"
CP[Control Plane]
subgraph "Worker Nodes"
N1[Node 1\ncontainerd + runc]
N2[Node 2\ncontainerd + runc]
N3[Node 3\ncontainerd + runc]
end
subgraph "Pods"
P1[Pod 1]
P2[Pod 2]
P3[Pod 3]
P4[Pod 4]
end
end
DEV --> DF
DF --> BK
BK --> IMG
IMG --> DH
IMG --> ECR
IMG --> ACR
DH --> CP
ECR --> CP
ACR --> CP
CP --> N1
CP --> N2
CP --> N3
N1 --> P1
N1 --> P2
N2 --> P3
N3 --> P4
Containerization to K8s Deployment Flow
flowchart LR
A[Source Code\nApp Microservice] -->|Dockerfile| B[docker build]
B -->|OCI Image| C[Container Image]
C -->|docker push| D[Registry\nDocker Hub / ECR / ACR]
D -->|kubectl apply| E[Kubernetes\nDeployment]
E -->|scheduling| F[Pods on Workers]
F -->|expose| G[Service\nLoadBalancer / ClusterIP]
G -->|external routing| H[Ingress Controller]
H -->|HTTPS| I[Users]
style A fill:#4A90D9,color:#fff
style C fill:#2496ED,color:#fff
style D fill:#FF6B6B,color:#fff
style E fill:#326CE5,color:#fff
style F fill:#326CE5,color:#fff
style G fill:#326CE5,color:#fff
style H fill:#326CE5,color:#fff
Complete GitOps Pipeline
sequenceDiagram
participant Dev as Developer
participant AppRepo as App Git Repo
participant CI as CI Pipeline
participant Reg as Container Registry
participant CfgRepo as Config Git Repo
participant GitOps as GitOps Tool (ArgoCD/Flux)
participant K8s as Kubernetes Cluster
Dev->>AppRepo: git push (new code)
AppRepo->>CI: webhook trigger
CI->>CI: docker build
CI->>Reg: docker push (new image)
CI->>CI: run automated tests
CI->>CfgRepo: update image tag in deployment.yaml
CfgRepo->>GitOps: observe change (pull)
GitOps->>K8s: kubectl apply -f deployment.yaml
K8s->>K8s: rolling update of pods
K8s-->>Dev: deployment complete ✓
Shared Kernels vs VM Isolation Model
graph TB
subgraph "Shared Kernels Model (fast)"
HW1[Hardware]
OS1[Linux OS + SHARED Kernel]
CT1[containerd + runc]
C1A[Container A]
C1B[Container B]
C1C[Container C]
HW1 --> OS1 --> CT1
CT1 --> C1A
CT1 --> C1B
CT1 --> C1C
end
subgraph "VM Isolation Model (secure)"
HW2[Hardware]
OS2[Linux OS]
VM1[Micro-VM 1\nIsolated Kernel]
VM2[Micro-VM 2\nIsolated Kernel]
VM3[Micro-VM 3\nIsolated Kernel]
C2A[Container A]
C2B[Container B]
C2C[Container C]
HW2 --> OS2
OS2 --> VM1 --> C2A
OS2 --> VM2 --> C2B
OS2 --> VM3 --> C2C
end
7. Code Snippets
Reference Dockerfile
# ─── Stage 1: Build ───────────────────────────────────────────────────────────
FROM node:20-alpine AS builder
# Set working directory
WORKDIR /app
# Copy dependency files first (cache layer optimization)
COPY package.json package-lock.json ./
# Install dependencies
RUN npm ci --only=production
# ─── Stage 2: Production Image ────────────────────────────────────────────────
FROM node:20-alpine AS production
# Principle of least privilege: don't run as root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
# Copy dependencies from build stage
COPY --from=builder /app/node_modules ./node_modules
# Copy source code
COPY . .
# Change file ownership
RUN chown -R appuser:appgroup /app
# Use non-root user
USER appuser
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
# Start command
CMD ["node", "server.js"]
Kubernetes Deployment YAML
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: production
labels:
app: myapp
version: v1.0
spec:
# Desired number of replicas (containers) — desired state
replicas: 4
selector:
matchLabels:
app: myapp
# Rolling update strategy (zero-downtime deployment)
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # max extra pods during update
maxUnavailable: 0 # no pods unavailable during update
template:
metadata:
labels:
app: myapp
version: v1.0
spec:
containers:
- name: myapp
image: myaccount/myapp:v1.0 # Image from Docker Hub
ports:
- containerPort: 3000
# Resources (limits and requests)
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
# Health checks
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
# Environment variables (no hardcoded secrets!)
env:
- name: NODE_ENV
value: "production"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password
# Spread pods across different nodes (high availability)
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: myapp
Kubernetes Service YAML
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: production
spec:
selector:
app: myapp # Targets all pods with this label
ports:
- protocol: TCP
port: 80 # Port exposed by the Service
targetPort: 3000 # Container port
# Service types:
# ClusterIP : accessible only within the cluster (default)
# NodePort : accessible from outside via node port
# LoadBalancer: creates a cloud load balancer (AWS ELB, Azure LB, etc.)
type: ClusterIP
---
# For external access via cloud load balancer:
apiVersion: v1
kind: Service
metadata:
name: myapp-lb
namespace: production
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
Kubernetes Ingress YAML
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: production
annotations:
# Annotations depend on ingress controller used (nginx, traefik, etc.)
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# Rate limiting
nginx.ingress.kubernetes.io/limit-rps: "100"
spec:
# TLS / HTTPS
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls-secret # Secret containing the SSL certificate
rules:
- host: myapp.example.com
http:
paths:
# Main route to frontend app
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
# Route to backend API
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
Reference docker-compose.yml
# docker-compose.yml (local development)
version: "3.9"
services:
# Frontend application
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- API_URL=http://backend:8080
depends_on:
backend:
condition: service_healthy
networks:
- app-network
# Backend application / API
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- DB_HOST=postgres
- DB_PORT=5432
- DB_NAME=myapp
- DB_USER=appuser
- DB_PASSWORD=${DB_PASSWORD} # Env variable from .env
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
networks:
- app-network
# PostgreSQL database
postgres:
image: postgres:16-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=appuser
- POSTGRES_PASSWORD=${DB_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser -d myapp"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
# Redis cache
redis:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
networks:
- app-network
volumes:
postgres_data:
networks:
app-network:
driver: bridge
8. Reference Tables
Docker vs kubectl Commands
| Action | Docker | kubectl |
|---|---|---|
| List running resources | docker ps | kubectl get pods |
| List all resources | docker ps -a | kubectl get pods --all-namespaces |
| View logs | docker logs <id> | kubectl logs <pod> |
| Execute a command | docker exec -it <id> bash | kubectl exec -it <pod> -- bash |
| Inspect a resource | docker inspect <id> | kubectl describe pod <pod> |
| Build an image | docker build -t name:tag . | (handled by CI/CD) |
| Push to registry | docker push name:tag | (handled by CI/CD) |
| Pull from registry | docker pull name:tag | (automatic on deploy) |
| Stop a container | docker stop <id> | kubectl delete pod <pod> |
| Remove a resource | docker rm <id> | kubectl delete deployment <name> |
| Scale | docker-compose up --scale app=3 | kubectl scale deployment <name> --replicas=3 |
| Apply a config | docker-compose up -f compose.yml | kubectl apply -f deployment.yaml |
| View resource config | docker inspect <id> | kubectl get deployment <name> -o yaml |
| View events | docker events | kubectl get events |
| Port forwarding | docker run -p 8080:80 | kubectl port-forward pod/<name> 8080:80 |
| View system resources | docker stats | kubectl top pods |
| Rollout history | (N/A) | kubectl rollout history deployment/<name> |
| Rollback | (rebuild) | kubectl rollout undo deployment/<name> |
Essential Kubernetes Objects
| K8s Object | Description | Usage |
|---|---|---|
| Pod | Basic unit — 1 or more containers sharing network and storage | Rarely created directly |
| Deployment | Manages pod replicas with rolling updates and self-healing | Stateless apps in production |
| StatefulSet | Like Deployment but with stable identity (for DBs, etc.) | PostgreSQL, MongoDB, Kafka |
| DaemonSet | 1 pod per node (automatically) | Monitoring agents, log collectors |
| Service (ClusterIP) | Exposes pods internally within the cluster | Inter-service communication |
| Service (LoadBalancer) | Exposes pods via a cloud load balancer | Simple external access |
| Ingress | HTTP/HTTPS routing to services, TLS management | Main entry point |
| ConfigMap | Non-sensitive configuration storage | Env variables, config files |
| Secret | Sensitive data storage (base64 encoded) | Passwords, tokens, certificates |
| PersistentVolume (PV) | Storage resource in the cluster | Cloud disks, NFS |
| PersistentVolumeClaim (PVC) | Storage request by a pod | Claim a PV |
| Namespace | Logical isolation within a cluster | dev/staging/prod separation |
| HorizontalPodAutoscaler | Automatic scaling based on metrics | Automatic load management |
| NetworkPolicy | Firewall rules between pods | Intra-cluster network security |
OCI Specs — Summary
| OCI Spec | Problem solved | Implementation example |
|---|---|---|
| Image Spec | Standard format for container images | Docker images, Podman images |
| Distribution Spec | Standard API for push/pull of images | Docker Hub, AWS ECR, GitHub Container Registry |
| Runtime Spec | Standard execution of containers | runc, crun, kata-containers |
Guarantee: An image built with Docker (Image Spec) → pushed to Docker Hub (Distribution Spec) → run by Kubernetes via containerd/runc (Runtime Spec) = it works, always.
9. Key Concepts to Remember
Fundamental Principles
1. Image Immutability
A container image is immutable. You never modify an image while it’s running. To update, build a new image with a new tag and redeploy.
2. Declarative vs Imperative
Kubernetes works in declarative mode: you declare the desired state (desired state) in YAML files, and Kubernetes continuously ensures the cluster matches that state.
3. Everything in Git
GitOps principle: everything — application code AND infrastructure configuration — belongs in Git. Git is the single source of truth. Absolute exception: secrets do not go in Git (use HashiCorp Vault, AWS Secrets Manager, Kubernetes Secrets with encryption at rest).
4. Microservices and single responsibility
Each microservice does one thing and exposes it via a REST API. Each microservice = its own container image = its own independent deployment cycle.
5. Self-healing by design
Never rely on a container or node being always available. Design for failure. Kubernetes automatically detects and fixes failures.
Essential Terminology
| Term | Quick definition |
|---|---|
| Container | Running instance of an image, in an isolated environment |
| Container Image | Immutable blueprint of a container (application + dependencies) |
| Registry | Container image repository (Docker Hub, ECR, ACR, GCR) |
| Containerization | Action of packaging an app into a container image |
| Orchestration | Automated management of containers at scale |
| Desired State | What you declare wanting in your K8s YAML files |
| Current State | The actual state of the cluster at a given moment |
| Self-healing | Kubernetes automatically brings current state = desired state |
| Rolling Update | Progressive update without service interruption |
| GitOps | Pattern where Git is the source of truth for deployments |
| Pull-based | Cluster pulls its configuration from Git (vs push) |
| Node | Machine (physical or VM) in the Kubernetes cluster |
| Pod | Smallest deployable unit in Kubernetes (1+ containers) |
| Replica | Identical copy of a pod for high availability and scaling |
| Namespace | Logical isolation in a K8s cluster |
Anti-Patterns to Avoid
| Anti-pattern | What to do instead |
|---|---|
Modifying a running container (docker exec → edit) | Build a new image, redeploy |
| Storing secrets in images or YAML files | Use Kubernetes Secrets + encryption, or Vault |
| Single replica in production | Minimum 2-3 replicas with PodDisruptionBudget |
| No resource limits/requests | Always define resources.requests and resources.limits |
| Running as root in the container | USER nonrootuser in the Dockerfile |
Direct kubectl exec access in production | Use GitOps + observability (logs, metrics) |
Images with latest tag in production | Always use precise tags (e.g.: v1.2.3 or SHA) |
Search Terms
docker · kubernetes · dynamic · duo · containerization · containers · architecture · deployment · gitops · model · oci · workflow · container · isolation · kernels · reference · shared · yaml · cloud · cncf · concepts · essential · history · microservices