New — Kubernetes Advanced Networking

Learn DevOps
the right way.

Deep-dive tutorials on Docker, Kubernetes, CI/CD, Terraform, AWS, and MLOps — written by engineers who run these in production.

50+
Tutorials
8
Tools
100%
Free
24/7
Online
terminal — devopsclicks.com
$ kubectl get pods -n production
NAME READY STATUS
api-7d4f9b-k2l9p 1/1 Running
worker-5c8fd-j4mwp 1/1 Running
 
$ terraform plan
Plan: 3 to add, 1 to change, 0 to destroy
 
$ docker build -t app:v2 .
Step 1/8 : FROM node:20-alpine
Step 2/8 : WORKDIR /app
Successfully tagged app:v2 ✓
 
$ ansible-playbook deploy.yml
ok=8 changed=3 failed=0
☸️  Kubernetes
🐳  Docker
🏗️  Terraform
⚙️  CI/CD
🔧  Ansible
🔀  Git
📊  Monitoring
🤖  MLOps
Featured Tutorials
Start learning today
Production-grade tutorials with real commands, architecture diagrams, and best practices.
Complete Guides
Master DevOps Tools
Comprehensive guides covering everything from fundamentals to production-ready deployments.
🐳
Docker Complete Guide
From container fundamentals to production-grade images, networking, volumes, and Docker Compose.
Explore Guide
☸️
Kubernetes Mastery Guide
Container orchestration from fundamentals to production — deployments, services, storage, and security.
Explore Guide
Knowledge Hub
All Tutorials
Deep dives and command references for every major DevOps tool.
🐳
Docker Complete Guide
From container fundamentals to production-grade images, networking, volumes, and Docker Compose.
Explore Guide
☸️
Kubernetes Mastery Guide
Container orchestration from fundamentals to production — deployments, services, storage, and security.
Explore Guide
//
// Add nav: 🐳 Docker // ============================================================ ?>
🐳  Complete Hands-On Reference

Docker Complete Guide

From container fundamentals to production-grade images, networking, volumes, registries, and Docker Compose — everything you need to ship confidently.

12
Chapters
2hr
Content
100%
Hands-On
01🐳

Introduction to Docker

Why Containers Changed Software Delivery

Docker is a tool designed to create, deploy, and run applications easily using containers. It packages your application along with all its dependencies into a single portable bundle called an image — so the app behaves identically everywhere it runs, from developer laptop to production server.
Problems Docker Solves
🔧
Works on My Machine — Fixed
Docker packages the application AND all dependencies into one image. No more version mismatches between dev, QA, staging, and production environments.
🔒
Application Isolation
Run multiple apps with conflicting dependencies on the same host inside isolated containers — no interference, no version conflicts between services.
Lightweight & Fast
Containers share the host OS kernel — no guest OS overhead. They start in seconds, not minutes. Much smaller in size than VMs (megabytes vs gigabytes).
🚀
Rapid Deployment
Build once, run anywhere. Same image runs on developer laptop, CI/CD pipeline, and production cluster. Deployment becomes predictable and repeatable.
Core Docker Concepts
📦
Image
A lightweight, standalone, executable package containing everything needed to run an application: code, runtime, libraries, environment variables, and config files. Think of it as a class blueprint.
🏃
Container
A running instance of an image. An isolated environment where your application executes. Multiple containers can run from the same image simultaneously — like objects from a class.
🗄️
Registry
A storage and distribution system for Docker images. Docker Hub is the public registry. AWS ECR, Azure ACR, and GCR are popular private registries.
🔧
Docker Engine
The client-server application that builds and runs containers. Includes the Docker daemon (server), REST API, and CLI client.
⚡ Advanced Engineering Notes

Docker uses Linux kernel features — namespaces (for isolation) and cgroups (for resource limits) — to create containers. Namespaces partition OS resources so each container sees its own isolated set (network, filesystem, process tree). cgroups limit how much CPU, memory, and I/O a container can use. On Mac and Windows, Docker Desktop runs a lightweight Linux VM to host the Docker daemon, which is why you'll find volume data stored inside that VM. In production, containers run natively on Linux hosts without any VM overhead.

02🔧

Docker Architecture

Engine, Daemon, Client & Registry

Docker uses a client-server architecture. The Docker client (CLI) sends commands to the Docker daemon, which does all the heavy lifting — building images, running containers, managing networks and volumes. The daemon pulls images from registries like Docker Hub when needed.
↳ Docker Architecture Overview
DOCKER CLIENTdocker builddocker pulldocker rundocker pushREST APIDOCKER HOSTDocker Daemon(dockerd) — builds & runsImagesContainersRunning Containersapidbuipull/pushREGISTRYDocker Hubhub.docker.comAWS ECRPrivate RegistryAzure ACRPrivate Registry
Architecture Components
ComponentRole
Docker Client (CLI)The tool you type commands into. Sends instructions to the daemon via REST API. Examples: docker build, docker run, docker push.
Docker Daemon (dockerd)Long-running background process. Manages images, containers, networks, and volumes. Listens for API requests.
Docker ImagesRead-only templates used to create containers. Stored as layered filesystems. Pulled from or pushed to registries.
Docker ContainersRunning instances of images. Isolated using Linux namespaces and cgroups. Has its own network interface, filesystem, and process space.
Docker RegistryStorage for Docker images. Docker Hub is the default public registry. AWS ECR, Azure ACR, GCR are private options.
Docker VolumesPersistent storage mechanism. Data survives container deletion. Managed by Docker CLI independently of containers.
⚡ Advanced Engineering Notes

The Docker daemon communicates with the container runtime (containerd) which actually creates and manages containers. This separation was introduced to allow Kubernetes and Docker to share containerd as a common runtime. On Linux, the Docker socket is at /var/run/docker.sock — mounting this socket into a container gives it full Docker control (dangerous in production). The Docker REST API is versioned — always check compatibility when upgrading Docker Engine in production environments.

03⚙️

Installing Docker

Docker Desktop & Docker Engine Setup

Docker Desktop is the recommended way to get Docker on Mac and Windows. It includes the Docker Engine, Docker CLI, Docker Compose, and a VM to host the Linux kernel. On Linux servers, you install Docker Engine directly — no VM required, maximum performance.
Prerequisites & Platform Options
PlatformInstall MethodNotes
Mac (Apple Silicon / Intel)Docker Desktop from docker.comIncludes Docker Engine, Compose, Kubernetes. Uses lightweight VM.
WindowsDocker Desktop with WSL2 backendWSL2 provides near-native Linux performance on Windows.
Ubuntu / DebianDocker Engine via apt repositoryapt-get install docker-ce docker-ce-cli containerd.io
RHEL / CentOSDocker Engine via yum repositoryyum install docker-ce — best for production servers.
All PlatformsVerify with: docker versionShows client + server version. Both must show correctly.
Post-Install Commands
docker versionVerify client and server are running correctly
docker infoFull system info — containers, images, storage driver
docker run hello-worldQuick sanity check — pulls and runs test image
systemctl enable dockerAuto-start Docker on server reboot (Linux)
usermod -aG docker $USERAdd current user to docker group (no sudo needed)
💡 Production Tip

On production Linux servers, always pin Docker to a specific version — avoid auto-upgrades that could break your workloads. Use: apt-mark hold docker-ce after installing. Test upgrades in staging first.

⚡ Advanced Engineering Notes

Docker Desktop on Mac runs a stripped-down Linux VM (using Apple's Hypervisor framework on M1/M2, or HyperKit on Intel). All container data, volumes, and the Docker daemon run inside this VM. This is why docker inspect shows volume paths like /var/lib/docker/volumes — that path is inside the VM, not on your Mac filesystem. On Apple Silicon (M1/M2/M3), Docker uses Rosetta 2 for amd64 images — most work fine but some performance-sensitive workloads may need arm64-native images. Use --platform linux/amd64 to force x86 emulation.

04💻

Essential Docker Commands

Images, Containers & Lifecycle Management

Docker CLI follows a consistent pattern: docker [management-command] [sub-command] [options]. Master these commands and you can manage any Docker environment confidently. Use --help with any command for detailed options.
Image Commands
docker imagesList all local images with size and tag
docker pull nginx:1.25Download specific image version from registry
docker pull nginx:latestDownload latest tag (default if no tag given)
docker rmi nginx:1.24Delete an image (must stop containers using it first)
docker image pruneRemove all dangling (untagged) images
docker image inspect nginxDetailed JSON info about an image
docker history nginxShow layers that make up the image
Container Commands
docker run nginxCreate and start a container (foreground)
docker run -d nginxRun container in detached (background) mode
docker run -d -p 8080:80 nginxMap port 8080 on host to port 80 in container
docker run --name my-nginx nginxAssign a custom name to the container
docker run -e MONGO_USER=admin mongoPass environment variable to container
docker psList running containers
docker ps -aList ALL containers (running + stopped)
docker stop my-nginxGracefully stop a container (sends SIGTERM)
docker start my-nginxStart a stopped container
docker restart my-nginxStop then start a container
docker rm my-nginxDelete a stopped container
docker rm -f my-nginxForce delete a running container
docker logs my-nginxView container logs
docker logs -f my-nginxStream container logs in real-time
docker exec -it my-nginx bashOpen interactive shell inside running container
docker rename old-name new-nameRename an existing container
docker inspect my-nginxFull JSON details about a container
docker statsReal-time CPU/memory usage of all containers
docker top my-nginxShow processes running inside container
Cleanup Commands
docker stop $(docker ps -q)Stop ALL running containers
docker rm $(docker ps -aq)Remove ALL stopped containers
docker system pruneRemove stopped containers, networks, dangling images
docker system prune -aRemove everything not used by running containers
💡 Port Mapping Rule

Host port must be unique — two containers cannot bind the same host port. But multiple containers can listen on the same container port (e.g., both on port 80 internally). Use -p 8080:80 -p 8081:80 for two nginx containers.

⚡ Advanced Engineering Notes

Docker commands evolved from docker run, docker ps etc. to docker container run, docker container ps in newer versions (management command format). Both work, but the management command format is cleaner in scripts. Use docker container ls --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" for readable output in CI pipelines. The --rm flag automatically removes the container when it exits — useful for one-off tasks and CI jobs to avoid container accumulation.

05🌐

Docker Networking

Bridge, Host & Custom Networks

Every container gets its own network namespace with a unique IP address. Docker provides several network drivers. Understanding networks is essential for connecting microservices, databases, and apps running in separate containers.
Network Types
🌉
Bridge (Default)
The default network for containers. Containers on the same bridge network can communicate by IP. The default bridge network does NOT support DNS-based container name resolution — use a custom bridge network for that.
🔀
Custom Bridge
User-defined bridge networks. Containers communicate using container NAMES (not just IPs) — Docker provides automatic DNS resolution. Always use custom bridge networks for multi-container apps.
🖥️
Host
Container shares the host's network namespace directly. No port mapping needed. Best performance. Not available on Docker Desktop (Mac/Windows). Use for performance-sensitive tools.
🔒
None
Container has no network access. Completely isolated. Use for batch jobs or security-sensitive processing that should never touch the network.
Network Commands
docker network lsList all Docker networks
docker network create my-netCreate a custom bridge network
docker network create --driver bridge my-netExplicitly specify bridge driver
docker network inspect my-netDetailed info including connected containers
docker network rm my-netDelete a network (no containers attached)
docker run --network my-net mongoRun container in a specific network
docker network connect my-net containerConnect running container to network
docker network disconnect my-net containerDisconnect container from network
Connecting MongoDB + Express (Hands-On)
BASH# Step 1: Create custom bridge network docker network create mongo-net # Step 2: Run MongoDB in custom network with a name docker run -d \ --name mongodb \ --network mongo-net \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=password \ mongo:4.4 # Step 3: Run Mongo Express — connect to MongoDB by container NAME docker run -d \ --name mongo-express \ --network mongo-net \ -p 8081:8081 \ -e ME_CONFIG_MONGODB_SERVER=mongodb \ mongo-express # Access at: http://localhost:8081 # "mongodb" resolves because both containers are on the same custom bridge network
💡 Key Difference

Default bridge: containers must use IP addresses to talk to each other. Custom bridge: containers talk by name (e.g., mongodb, api-service). Always use custom bridge networks for microservices.

⚡ Advanced Engineering Notes

Docker DNS works by embedding a DNS server inside the Docker daemon that resolves container names within the same user-defined network. This is why custom bridge networks support name resolution but the default bridge network does not — the default bridge predates the embedded DNS feature. In production, Docker overlay networks enable multi-host communication across a Docker Swarm cluster. For Kubernetes environments, the container networking is handled by CNI plugins (Calico, Cilium, Flannel) rather than Docker networking. MacVLAN and IPVLAN network drivers are used when containers need to appear as physical devices on the host network — useful in bare-metal networking scenarios.

06📄

Writing Dockerfiles

Instructions, Layers & Best Practices

A Dockerfile is a text document containing instructions to build a Docker image. Docker builds images by executing each instruction in order — each instruction creates a new read-only layer. Mastering Dockerfile instructions lets you build lean, secure, production-ready images.
Core Dockerfile Instructions
InstructionDescriptionExample
FROMSets the base image. Every Dockerfile starts with FROM.FROM openjdk:18-jdk-alpine
WORKDIRSets working directory for subsequent instructions.WORKDIR /app
COPYCopies files from build context to image filesystem.COPY target/app.jar /app/app.jar
ADDLike COPY but also supports URLs and tar extraction.ADD app.tar.gz /app/
RUNExecutes commands during build time — creates a new layer.RUN npm install
ENVSets environment variables available at runtime.ENV NODE_ENV=production
ARGBuild-time variable — passed via --build-arg flag.ARG JAVA_VERSION=18-jdk
EXPOSEDocuments which port the container listens on (informational).EXPOSE 8080
ENTRYPOINTDefines the command that always runs. Args are appended.ENTRYPOINT ["java", "-jar"]
CMDDefault command/args. Overridden by docker run arguments.CMD ["app.jar"]
VOLUMECreates a mount point for external volumes.VOLUME ["/data"]
LABELAdds metadata key-value pairs to the image.LABEL version="1.0"
Spring Boot Application Dockerfile
DOCKERFILE# ── Spring Boot Dockerfile ───────────────────────────────── # ARG allows passing Java version at build time: # docker build --build-arg JAVA_VERSION=18-jdk-alpine . ARG JAVA_VERSION=18-jdk-alpine FROM openjdk:${JAVA_VERSION} # Set working directory WORKDIR /app # Copy the pre-built JAR file COPY target/todo-api-1.0.0.jar todo-api.jar # Document the port (does not actually publish it) EXPOSE 8080 # Run the application ENTRYPOINT ["java", "-jar", "todo-api.jar"]
docker build -t todo-api:1.0.0 .Build image with tag from Dockerfile in current dir
docker build -f Dockerfile.prod -t app:prod .Build using a specific Dockerfile name
docker build --build-arg JAVA_VERSION=17-jdk -t app .Pass build-time argument
docker run -d -p 8080:8080 todo-api:1.0.0Run the built image
⚡ Advanced Engineering Notes

ENTRYPOINT vs CMD: ENTRYPOINT defines the fixed executable that always runs; CMD provides default arguments that can be overridden at docker run time. Combining them: ENTRYPOINT ["java", "-jar"] CMD ["app.jar"] — you can override just the jar name at runtime with docker run myimage different-app.jar. Use exec form (["java", "-jar"]) not shell form (java -jar) for ENTRYPOINT so the process receives OS signals directly — critical for graceful shutdown handling. ARG variables are NOT available at runtime (only during build). Use ENV for runtime variables. Never put secrets in ENV in Dockerfiles — use Docker secrets or environment injection at deployment time.

07

Docker Best Practices

Multi-Stage Builds, Caching & .dockerignore

Production-grade Docker images are lean, fast to build, and secure. Three key techniques transform a naive Dockerfile into a production-ready one: multi-stage builds (reduce image size dramatically), layer caching (speed up rebuild times), and .dockerignore (reduce build context size).
Multi-Stage Builds — React.js Example
DOCKERFILE# ── Stage 1: Build the React artifacts ───────────────────── FROM node:20-alpine AS builder WORKDIR /app # Copy only package files first (enables layer caching) COPY package*.json ./ RUN npm ci --only=production # Copy source code and build COPY . . RUN npm run build # ── Stage 2: Serve with Nginx ──────────────────────────────── # Only the artifacts from Stage 1 are copied — no node_modules! FROM nginx:stable-alpine # Copy built artifacts to nginx html directory COPY --from=builder /app/build /usr/share/nginx/html # Copy nginx config for React Router support COPY nginx.conf /etc/nginx/conf.d/default.conf CMD ["nginx", "-g", "daemon off;"] # Result: ~22MB image vs ~500MB single-stage image!
Layer Caching Strategy
DOCKERFILE# ── BAD: Source code changes invalidate npm install ───────── FROM node:20-alpine WORKDIR /app COPY . . # ← copies everything — cache busted on any change RUN npm install # ← re-runs every single time! # ── GOOD: Separate dependency install from source copy ─────── FROM node:20-alpine WORKDIR /app COPY package*.json ./ # ← only changes when dependencies change RUN npm install # ← cached unless package.json changes! COPY . . # ← source changes do NOT re-trigger npm install RUN npm run build
The .dockerignore File
BASH# .dockerignore — lives in same directory as Dockerfile # Docker sends entire build context (current dir) to daemon # .dockerignore prevents sending unnecessary files node_modules .git .gitignore *.md dist build .DS_Store *.log .env .env.* coverage __tests__ *.test.js Dockerfile*
Image Size Comparison
ApproachImage SizeBuild Time
Single-stage (npm start)~520 MBSlow (no caching)
Single-stage (serve build)~480 MBSlow (no caching)
Multi-stage (Nginx)~22 MBFast (with caching)
Multi-stage + cache + ignore~22 MBVery fast (cached layers)
Use alpine base images when possible — node:20-alpine is 180MB vs node:20 at 1GB
Copy package.json BEFORE source code to maximise layer cache hits
Use npm ci (clean install) not npm install in production Dockerfiles for reproducible builds
Add .dockerignore to exclude node_modules, .git, build artifacts from build context
Use multi-stage builds for compiled apps (React, Spring Boot, Go) to strip build tools
Pin base image versions explicitly — never use :latest in production Dockerfiles
Run as non-root user in production: adduser -D appuser && USER appuser
Scan images for vulnerabilities: docker scout quickview my-image or trivy image my-image
⚡ Advanced Engineering Notes

Layer caching works by hashing each instruction and its inputs. If the hash matches a cached layer, Docker reuses it without re-executing. COPY instructions are sensitive — Docker checksums file contents. For Go applications, use: COPY go.mod go.sum ./ then RUN go mod download before copying source. For Java Maven apps: COPY pom.xml ./ then RUN mvn dependency:go-offline. BuildKit (enabled by default in Docker 23+) adds parallel stage building, better caching, and cache mounts (RUN --mount=type=cache,target=/root/.m2 mvn package) that dramatically speed up builds in CI pipelines.

08💾

Docker Volumes

Data Persistence & Bind Mounts

Containers are ephemeral — when a container is deleted, all data written inside it is gone. Docker Volumes solve this by storing data outside the container lifecycle, on the host filesystem. Volumes are the recommended way to persist data for databases and stateful applications.
Storage Options Comparison
TypeDescriptionBest For
Named VolumeDocker manages the storage location. Created with docker volume create.Databases (MongoDB, PostgreSQL, MySQL)
Anonymous VolumeAuto-created by Docker with a random name. Not reusable easily.Temporary scratch space
Bind MountMaps a specific host directory path into the container.Dev workflow — edit code on host, see changes in container instantly
Named Volumes — MongoDB Example
BASH# Step 1: Create a named volume docker volume create mongo-data # Step 2: Run MongoDB with the volume mounted docker run -d \ --name mongodb \ --network mongo-net \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=password \ -v mongo-data:/data/db \ mongo:4.4 # /data/db is where MongoDB stores its data inside the container # It is now mapped to the "mongo-data" volume on the host # Step 3: Delete the container — data is PRESERVED docker stop mongodb && docker rm mongodb # Step 4: Recreate — data is RESTORED automatically docker run -d --name mongodb --network mongo-net \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=password \ -v mongo-data:/data/db mongo:4.4
Volume Commands
docker volume create mongo-dataCreate a named volume
docker volume lsList all volumes
docker volume ls -f name=mongoFilter volumes by name
docker volume inspect mongo-dataShow volume details including host path
docker volume rm mongo-dataDelete a volume (no container must be using it)
docker volume pruneRemove all unused volumes
docker inspect mongodbShows Mounts section with volume binding
Bind Mount — Development Workflow
BASH# Bind mount: map local source code into container # Changes on host reflect instantly in container docker run -d \ -p 3000:3000 \ -v /Users/dev/my-app:/app \ --name dev-server \ node:20-alpine sh -c "cd /app && npm install && npm start" # Common DB volume paths to mount: # MongoDB: -v my-vol:/data/db # PostgreSQL: -v my-vol:/var/lib/postgresql/data # MySQL: -v my-vol:/var/lib/mysql # Jenkins: -v my-vol:/var/jenkins_home
⚠️ Never delete volumes carelessly

Deleting a volume permanently destroys all data stored in it. Docker does NOT delete volumes when you delete containers — this is intentional protection. Always backup volume data before deleting. Use docker volume rm only when you are certain the data is no longer needed.

⚡ Advanced Engineering Notes

Volumes are stored at /var/lib/docker/volumes/ on Linux hosts and inside the Docker Desktop VM on Mac/Windows. Docker volume drivers (like Rex-Ray, Portworx, AWS EFS driver) enable volumes that span multiple hosts — essential for stateful containers in Docker Swarm or Kubernetes. In Kubernetes, this concept maps to PersistentVolumes and PersistentVolumeClaims. Bind mounts are great for development but should not be used in production — they tie the container to a specific host path and break portability. For application configuration in production, use Docker secrets or environment variables instead of bind-mounting config files.

09📦

Docker Registry & AWS ECR

Pushing & Pulling Images

A registry is storage and distribution for Docker images — like GitHub but for container images. Once you build an image locally, push it to a registry so it can be pulled on any other machine: CI/CD pipelines, staging servers, production clusters.
Registry Options
🌍
Docker Hub
Public/private registry. Free tier with limited private repos. Pull rate limits apply. hub.docker.com — the default registry Docker uses.
☁️
AWS ECR
Amazon Elastic Container Registry. Private, fully managed. Integrates with EKS, ECS, CodePipeline. Pay per storage and data transfer.
🔷
Azure ACR
Azure Container Registry. Integrates with AKS and Azure DevOps. Geo-replication available in premium tier.
🔑
Self-Hosted
Run docker run -d -p 5000:5000 registry:2 — your own private registry. Full control, no rate limits. Needs HTTPS for production.
Push to Docker Hub
BASH# Step 1: Login to Docker Hub docker login # Enter: username and password # Step 2: Tag your image with your Docker Hub username # Format: username/repository:tag docker tag todo-api:1.0.0 myusername/todo-api:1.0.0 # Step 3: Push to Docker Hub docker push myusername/todo-api:1.0.0 # Step 4: Pull on another machine docker pull myusername/todo-api:1.0.0
Push to AWS ECR
BASH# Step 1: Create ECR repository in AWS Console or CLI aws ecr create-repository --repository-name todo-api --region ap-south-1 # Step 2: Authenticate Docker to ECR aws ecr get-login-password --region ap-south-1 | \ docker login --username AWS --password-stdin \ 123456789.dkr.ecr.ap-south-1.amazonaws.com # Step 3: Tag image with ECR URI docker tag todo-api:1.0.0 \ 123456789.dkr.ecr.ap-south-1.amazonaws.com/todo-api:1.0.0 # Step 4: Push to ECR docker push 123456789.dkr.ecr.ap-south-1.amazonaws.com/todo-api:1.0.0 # Step 5: Pull on EC2 instance or EKS (automatically uses IAM role) docker pull 123456789.dkr.ecr.ap-south-1.amazonaws.com/todo-api:1.0.0
💡 ECR Lifecycle Policy

Set ECR lifecycle policies to auto-delete old image tags and control storage costs: keep only last 10 images per repository. In AWS Console → ECR → Repository → Lifecycle Policy.

⚡ Advanced Engineering Notes

ECR integrates seamlessly with IAM — EC2 instances and ECS tasks with the right IAM role can pull images without any explicit login command. For Kubernetes (EKS), use the ecr-credential-helper or the ECR public gallery for public images. ECR image scanning (powered by Clair/Inspector) automatically scans images for known CVEs on push. Enable immutable image tags in ECR production repos to prevent accidental tag overwriting — once pushed, a tag cannot be overwritten. Container image signing with AWS Signer or Cosign/Sigstore provides supply chain security verification.

10🔀

Docker Compose

Multi-Container Applications

Docker Compose lets you define and run multi-container applications with a single YAML file. Instead of running separate docker run commands for your API, database, and UI, Compose brings them all up together with one command: docker compose up.
Full Stack Docker Compose — React + Spring Boot + MongoDB
YAMLversion: "3.9" services: # ── MongoDB Database ────────────────────────────────── mongodb: image: mongo:4.4 container_name: mongodb environment: MONGO_INITDB_ROOT_USERNAME: admin MONGO_INITDB_ROOT_PASSWORD: password volumes: - mongo-data:/data/db # persist data networks: - app-network restart: unless-stopped # ── Spring Boot API ─────────────────────────────────── todo-api: image: myusername/todo-api:1.0.0 container_name: todo-api environment: SPRING_DATA_MONGODB_HOST: mongodb # uses container name as DNS SPRING_DATA_MONGODB_PORT: 27017 SPRING_DATA_MONGODB_DATABASE: todos ports: - "8080:8080" networks: - app-network depends_on: - mongodb # start after mongodb restart: unless-stopped # ── React.js UI ─────────────────────────────────────── todo-ui: image: myusername/todo-ui:1.0.0 container_name: todo-ui ports: - "3000:80" # nginx serves on port 80 networks: - app-network depends_on: - todo-api restart: unless-stopped # ── Named Volumes ───────────────────────────────────────── volumes: mongo-data: # ── Custom Network ──────────────────────────────────────── networks: app-network: driver: bridge
Docker Compose Commands
docker compose upStart all services (foreground — see logs)
docker compose up -dStart all services in detached mode
docker compose up -d todo-apiStart only a specific service
docker compose downStop and remove all containers + networks
docker compose stopStop services without removing containers
docker compose startStart stopped services
docker compose restart todo-apiRestart a single service
docker compose logsView logs from all services
docker compose logs -f todo-apiStream logs from a specific service
docker compose psShow status of all services
docker compose buildBuild/rebuild service images
docker compose pullPull latest images for all services
docker compose exec mongodb mongoshExecute a command in a running service
Key Compose Concepts
FeatureDescription
depends_onControls startup order. Service waits for listed services to be running (not healthy). Use with healthcheck for production.
networksServices on the same network communicate by service name as DNS. Auto-creates network if not specified.
volumesNamed volumes persist data across docker compose down/up cycles. Anonymous volumes do not.
restartnever / on-failure / always / unless-stopped. Use unless-stopped for production services.
environmentPass env vars to containers. Reference .env file variables with ${VAR_NAME}.
buildBuild image from local Dockerfile instead of pulling. Specify context and dockerfile path.
💡 Smart Partial Updates

When you change only one service in docker-compose.yml and run docker compose up -d — only that changed service is recreated. Other services are left untouched. This makes Compose very efficient for iterative development.

⚡ Advanced Engineering Notes

Docker Compose V2 (docker compose, no hyphen) is the current version — built in Go, ships with Docker Desktop, faster and more reliable than V1 (docker-compose, Python). Always use V2. Compose profiles (profiles: [dev]) let you define services that only start in certain environments — run docker compose --profile dev up to include dev-only services like mock servers or test databases. Compose Watch (docker compose watch) provides hot-reload for development: automatically rebuilds and restarts services when source files change — no more manual docker compose up --build cycles.

11⚖️

Docker vs Virtual Machines

Architecture, Performance & Trade-offs

Both containers and VMs solve the same fundamental problem: running multiple isolated workloads on shared hardware. But they solve it at different layers of the stack — VMs virtualise hardware, containers virtualise the OS. This architectural difference has massive implications for performance, size, and portability.
Architecture Comparison
AspectVirtual Machine (VM)Docker Container
Isolation LevelHardware virtualisation (hypervisor)OS-level virtualisation (namespaces/cgroups)
Guest OSFull OS per VM (GBs of overhead)Shares host OS kernel (no guest OS)
SizeGBs (OS + app + libs)MBs (app + libs only)
Startup TimeMinutes (boot full OS)Milliseconds (start process)
Resource UsageHigh (dedicated CPU/RAM per VM)Low (shared kernel, minimal overhead)
PortabilityImage tied to hypervisor typeRun on any Docker-compatible host
Security IsolationStronger (separate kernel per VM)Good but shared kernel is a larger attack surface
Use CaseLegacy apps, different OS, full isolationMicroservices, CI/CD, modern cloud-native apps
When to Use Each
🖥️
Use VMs When...
Running Windows and Linux workloads on the same host. Running applications that require full OS features. Compliance requirements demanding strong kernel isolation. Licensing requirements tied to specific OS versions.
🐳
Use Containers When...
Building microservices and cloud-native applications. Running many instances of the same service. CI/CD pipelines where fast build/run cycles matter. Modern 12-factor apps following containerisation principles.
🔀
Use Both Together
Most production environments combine both. VMs (EC2 instances) provide the infrastructure. Docker containers run on top of those VMs. Kubernetes orchestrates containers across the VM fleet.
⚡ Advanced Engineering Notes

AWS EC2 instances ARE virtual machines — when you run Docker containers on EC2, you have VMs running containers (both layers). AWS Fargate goes one step further: it abstracts away the EC2 VM and lets you run containers without managing any servers — fully serverless containers. The security model matters: containers share the host kernel, so a kernel exploit in one container potentially affects others. VMs with separate kernels prevent this. For highly sensitive multi-tenant workloads, use dedicated VMs per tenant or gVisor/Kata Containers which add a sandboxed kernel layer to containers, combining VM-level security with container-level performance.

12📋

Docker Quick Reference

Commands, Flags & Patterns

A quick-reference card for the most important Docker commands and patterns. Bookmark this chapter for fast lookups during development and production operations.
Most-Used Docker Commands
docker run -d -p 80:80 --name web nginxRun nginx detached on port 80
docker exec -it web bashInteractive shell into running container
docker logs web -f --tail=100Stream last 100 lines of logs
docker cp file.txt web:/app/Copy file from host to container
docker cp web:/app/log.txt .Copy file from container to host
docker commit web my-custom-imageCreate image from running container (avoid in prod)
docker save -o image.tar my-imageExport image to tar file
docker load -i image.tarImport image from tar file
docker stats --no-streamOne-time snapshot of resource usage
Dockerfile Quick Reference
FROMWORKDIRCOPYADDRUNENVARGEXPOSEENTRYPOINTCMDVOLUMELABELUSERHEALTHCHECKONBUILDSTOPSIGNAL
Key Flags Reference
FlagCommandMeaning
-ddocker runDetached mode (background)
-p host:containerdocker runPort mapping
-e KEY=valuedocker runEnvironment variable
-v vol:/pathdocker runVolume mount
--namedocker runAssign container name
--networkdocker runConnect to network
--rmdocker runAuto-remove on exit
-itdocker run / execInteractive terminal
-f / --filedocker buildSpecify Dockerfile name
-tdocker buildTag the built image
--build-argdocker buildPass ARG variable
-adocker psShow all containers (incl. stopped)
-qdocker psShow only container IDs
Production Best Practices Summary
Always use specific image tags in production — never :latest (non-deterministic builds)
Use multi-stage builds for compiled apps — reduces image size by 10-20×
Add .dockerignore to exclude node_modules, .git, .env from build context
Copy dependency files (package.json, pom.xml) before source code for better caching
Run as non-root user inside containers for security
Scan images with docker scout or trivy before pushing to production
Use named volumes for all database data — never rely on container filesystem
Set memory and CPU limits: docker run --memory=512m --cpus=1.0
Use health checks: HEALTHCHECK --interval=30s CMD curl -f http://localhost/health
Use restart: unless-stopped in docker-compose.yml for production services
Store secrets via environment injection or Docker secrets — never bake into images
Tag images with git commit SHA in CI/CD for full traceability
⚡ Advanced Engineering Notes

Docker BuildKit (now default in Docker 23+) unlocks advanced features: parallel multi-stage builds, cache mounts (persist package manager caches between builds), secret mounts (securely pass secrets during build without them landing in image layers), and SSH mounts (access private git repos during build). Cache mounts alone can reduce Node.js build times from 2 minutes to 10 seconds in CI. Example: RUN --mount=type=cache,target=/root/.npm npm ci. Container image signing with Cosign and the Sigstore project enables cryptographic verification that images haven't been tampered with between build and deployment — increasingly required in regulated industries and government cloud environments.

☸️ Complete Engineering Reference

Kubernetes Mastery Guide

A production-grade reference covering container orchestration — from fundamentals to advanced operations, security, and scaling.

01🎯

Introduction to Kubernetes

Container Orchestration Fundamentals

Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications. It solves the challenges of running containers in production — monitoring health, scaling on demand, and ensuring zero-downtime deployments.
Problems Kubernetes Solves
💀
Container Failures
What if a container crashes? Kubernetes monitors health and automatically restarts failed containers — this is called self-healing.
📈
Traffic Spikes
What if load increases 10x? Kubernetes scales your app by creating more replicas and load balancing traffic across them.
🔄
Deployment Downtime
What if deployment breaks the app? Kubernetes does rolling updates — replacing containers one by one with zero downtime.
Rollback Needed
What if the new version has bugs? Kubernetes can rollback to a previous version with a single command.
Key Features
FeatureDescription
Self-HealingAutomatically restarts failed containers and replaces pods when nodes die.
Auto ScalingScales applications up/down based on CPU, memory, or custom metrics.
Load BalancingDistributes traffic across multiple pod replicas automatically.
Rolling UpdatesDeploys new versions gradually without downtime.
Secret ManagementStores and manages sensitive data like passwords and API keys.
Automatic Bin PackingPlaces containers on nodes based on resource requirements.
Kubernetes vs Other Orchestrators
Docker SwarmKubernetes (K8s)Apache MesosAmazon ECSNomad
Kubernetes (K8s) is the most popular choice with advanced features and support from all major cloud providers. The name comes from Greek meaning "helmsman" — the person who steers a ship carrying containers.
02🏗️

Kubernetes Architecture

Control Plane & Worker Nodes

A Kubernetes cluster consists of a Control Plane (master) that manages the cluster, and Worker Nodes that run your applications. The control plane makes global decisions while worker nodes provide the runtime environment.
Control Plane Components
🌐
API Server
The front door to Kubernetes. All commands (kubectl, UI, SDK) go through the API server. It validates and processes requests.
💾
etcd
Distributed key-value store holding all cluster data — nodes, pods, configs, secrets. The single source of truth.
📋
Scheduler
Watches for new pods and assigns them to nodes based on resource requirements, affinity rules, and constraints.
🔄
Controller Manager
Runs controllers that maintain desired state — ReplicaSet controller, Node controller, Endpoint controller, etc.
Worker Node Components
🐳
Container Runtime
Software that runs containers (Docker, containerd, CRI-O). Pulls images and manages container lifecycle.
📡
Kubelet
Agent on each node that ensures containers are running in pods. Reports node and pod status to control plane.
🔀
Kube-proxy
Network proxy maintaining network rules on nodes. Handles routing traffic to correct pods and load balancing.
↳ Request Flow
kubectl
User command
API Server
Validates request
Scheduler
Picks node
Kubelet
Creates pod
⚡ Pro Tip

In production, run multiple control plane nodes for high availability. If etcd loses data, you lose your entire cluster state — always have backups!

03⚙️

Setup Kubernetes

Local Development & kubectl

For local development, use Minikube, Kind, or k3s to spin up a cluster on your machine. For production, use managed services like EKS, GKE, or AKS. kubectl is the CLI for interacting with any Kubernetes cluster.
Local Cluster Options
ToolBest ForNotes
MinikubeLearning, developmentMulti-node support, add-ons, VM or Docker driver
KindCI/CD, testingKubernetes in Docker, fast startup, multi-node
k3sEdge, IoT, low resourcesLightweight (~50MB), uses SQLite instead of etcd
Docker DesktopMac/Windows devBuilt-in K8s option, single node
Install kubectl
$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"Download kubectl binary
$ chmod +x kubectl && sudo mv kubectl /usr/local/bin/Make executable and move to PATH
$ kubectl version --clientVerify installation
Create Cluster with Minikube
$ minikube start --nodes=2 --driver=dockerCreate 2-node cluster with Docker
$ minikube statusCheck cluster status
$ kubectl get nodesList cluster nodes
$ minikube dashboard --urlOpen Kubernetes dashboard
kubectl Syntax
BASHkubectl <command> <resource-type> <name> <flags> # Examples: kubectl get pods # List all pods kubectl get pods -o wide # More details kubectl describe pod inventory-pod # Detailed info kubectl delete pod inventory-pod # Delete pod kubectl apply -f manifest.yaml # Apply config file
kubectl commands follow a consistent pattern: verb (get, create, delete, apply) + resource type (pods, services, deployments) + name + flags (-o yaml, -n namespace).
04📦

Kubernetes Pods

The Smallest Deployable Unit

A Pod is the smallest deployable unit in Kubernetes — a wrapper around one or more containers that share network and storage. Containers in a pod can communicate via localhost and share volumes.
Why Pods?
🔗
Shared Network
Containers in a pod share IP address and ports. They communicate via localhost.
💾
Shared Storage
Containers can mount the same volumes for data sharing.
♻️
Co-scheduling
Related containers (app + sidecar) are always scheduled together on same node.
🎯
Single IP
Each pod gets one IP. Multiple containers share it via different ports.
Pod Manifest
POD.YAMLapiVersion: v1 kind: Pod metadata: name: inventory-api labels: app: inventory tier: backend spec: containers: - name: api image: myregistry/inventory-api:v1 ports: - containerPort: 8080 resources: requests: memory: "128Mi" cpu: "100m"
Essential Pod Commands
$ kubectl apply -f pod.yamlCreate pod from manifest
$ kubectl get podsList pods in current namespace
$ kubectl get pods -l app=inventoryFilter pods by label
$ kubectl describe pod inventory-apiDetailed pod info + events
$ kubectl logs inventory-apiView container logs
$ kubectl logs inventory-api -fStream logs in real-time
$ kubectl exec -it inventory-api -- /bin/shShell into container
$ kubectl port-forward pod/inventory-api 8080:8080Forward local port to pod
$ kubectl delete pod inventory-apiDelete pod
Multi-Container Pods (Sidecars)
SIDECAR.YAMLapiVersion: v1 kind: Pod metadata: name: web-with-logger spec: containers: - name: web image: myregistry/web-app:v1 volumeMounts: - name: logs mountPath: /var/log/app - name: log-shipper image: fluent/fluentd:v1.14 volumeMounts: - name: logs mountPath: /var/log/app volumes: - name: logs emptyDir: {}
⚠️ Important

Pods are ephemeral — they can be killed and recreated anytime. Never deploy pods directly. Use Deployments or StatefulSets for production workloads.

05♾️

Deployments & ReplicaSets

Self-Healing & Rolling Updates

ReplicaSets ensure a specified number of pod replicas are always running. Deployments wrap ReplicaSets and add rollout management — enabling zero-downtime updates and easy rollbacks.
Why Not Just Pods?
🔄
Self-Healing
If a pod dies, ReplicaSet creates a replacement automatically.
📈
Scaling
Increase replicas from 2 to 10 with one command.
🔀
Load Distribution
Traffic spreads across replicas via Services.
Rollbacks
Deployment keeps history, rollback to any previous version.
↳ Deployment → ReplicaSet → Pods
Deployment
Manages rollouts
ReplicaSet
Maintains replicas
Pods
Run containers
Deployment Manifest
DEPLOYMENT.YAMLapiVersion: apps/v1 kind: Deployment metadata: name: catalog-service annotations: kubernetes.io/change-cause: "Initial release v1.0" spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app: catalog template: metadata: labels: app: catalog spec: containers: - name: catalog image: myregistry/catalog:v1.0 ports: - containerPort: 8080
Rollout Commands
$ kubectl rollout status deployment/catalog-serviceWatch rollout progress
$ kubectl rollout history deployment/catalog-serviceView revision history
$ kubectl rollout undo deployment/catalog-serviceRollback to previous
$ kubectl rollout undo deployment/catalog-service --to-revision=2Rollback to specific revision
$ kubectl scale deployment catalog-service --replicas=5Scale replicas
⚡ Pro Tip

Use kubernetes.io/change-cause annotation to document changes. It appears in rollout history and helps teams understand what changed in each revision.

06🌐

Kubernetes Services

Stable Networking & Load Balancing

Pods get random IPs that change on restart. Services provide stable endpoints that abstract away pod IPs — enabling reliable communication and automatic load balancing across replicas.
Service Types
TypeScopeUse Case
ClusterIPInternal onlyDefault. Inter-service communication within cluster.
NodePortExternal via nodeOpens port 30000-32767 on all nodes. Development use.
LoadBalancerExternal via cloud LBProvisions cloud load balancer. Production external access.
ExternalNameDNS aliasMaps service to external DNS name.
ClusterIP Service
SERVICE.YAMLapiVersion: v1 kind: Service metadata: name: catalog-service spec: type: ClusterIP selector: app: catalog ports: - port: 80 targetPort: 8080
port is what clients connect to (catalog-service:80). targetPort is the container port (8080). The selector matches pod labels to know which pods to route to.
Service Commands
$ kubectl get svcList services
$ kubectl describe svc catalog-serviceService details + endpoints
$ kubectl get endpoints catalog-servicePod IPs backing the service
$ kubectl port-forward svc/catalog-service 8080:80Local access for debugging
⚠️ Important

NodePort opens ports on every node — security concern in production. Use LoadBalancer or Ingress instead.

07🚪

Kubernetes Ingress

HTTP Routing & TLS

Each LoadBalancer service creates a separate cloud load balancer with its own cost. Ingress consolidates multiple services behind one load balancer with URL-based routing and TLS termination.
Why Ingress?
💰
Cost Efficient
One load balancer for all services instead of one per service.
🔀
Path Routing
Route /api to backend, / to frontend.
🏠
Host Routing
Route shop.example.com to shop, api.example.com to API.
🔒
TLS Termination
Handle HTTPS certificates in one place.
Ingress Manifest
INGRESS.YAMLapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: shop-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1 spec: ingressClassName: nginx tls: - hosts: - shop.example.com secretName: shop-tls rules: - host: shop.example.com http: paths: - path: /api/(.*) pathType: Prefix backend: service: name: shop-api port: number: 8080 - path: /(.*) pathType: Prefix backend: service: name: shop-frontend port: number: 80
Popular Ingress Controllers
NGINX IngressTraefikHAProxyAWS ALBKongIstio
⚡ Pro Tip

Use cert-manager to automatically provision and renew TLS certificates from Let's Encrypt.

08📁

Kubernetes Namespaces

Cluster Organization & Isolation

Namespaces are virtual clusters within a physical cluster. They organize resources, isolate teams, enable resource quotas, and allow the same resource names in different namespaces.
Default Namespaces
NamespacePurpose
defaultResources created without specifying namespace
kube-systemKubernetes system components (API server, scheduler, etc.)
kube-publicPublicly readable resources, cluster info
kube-node-leaseNode heartbeat leases for health detection
Working with Namespaces
$ kubectl create namespace developmentCreate namespace
$ kubectl get namespacesList all namespaces
$ kubectl get pods -n developmentList pods in namespace
$ kubectl get pods --all-namespacesList pods across all namespaces
$ kubectl config set-context --current --namespace=developmentSet default namespace
Namespace Manifest
NAMESPACE.YAMLapiVersion: v1 kind: Namespace metadata: name: production labels: env: prod
Cross-Namespace Communication
DNS# Full DNS name for services: <service-name>.<namespace>.svc.cluster.local # Examples: catalog-service.production.svc.cluster.local payment-api.payments.svc.cluster.local # Short form (within same cluster): catalog-service.production
⚠️ Important

Deleting a namespace deletes ALL resources in it. Be extremely careful with kubectl delete namespace in production!

09💾

Kubernetes Volumes

Persistent Storage

Container filesystems are ephemeral — data is lost when pods restart. Volumes provide persistent storage that survives pod restarts and can be shared between containers.
Volume Types
TypeLifetimeUse Case
emptyDirPod lifetimeScratch space, cache shared between containers
hostPathNode lifetimeAccess node filesystem (avoid in production)
configMap/secretPod lifetimeMount config files or secrets
persistentVolumeClaimIndependentDatabases, stateful apps — survives pod/node restarts
PersistentVolumeClaim
PVC.YAMLapiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgres-data spec: accessModes: - ReadWriteOnce storageClassName: standard resources: requests: storage: 10Gi
Using PVC in Pod
POD-PVC.YAMLapiVersion: v1 kind: Pod metadata: name: postgres spec: containers: - name: postgres image: postgres:15 volumeMounts: - name: data mountPath: /var/lib/postgresql/data volumes: - name: data persistentVolumeClaim: claimName: postgres-data
Access Modes
ModeDescription
ReadWriteOnce (RWO)Single node read-write
ReadOnlyMany (ROX)Many nodes read-only
ReadWriteMany (RWX)Many nodes read-write
⚡ Pro Tip

Use StorageClass with volumeBindingMode: WaitForFirstConsumer to create PVs in the same zone as the pod that needs them.

10🗄️

StatefulSets

Stateful Application Management

Deployments are for stateless apps where pods are interchangeable. StatefulSets are for stateful apps (databases) that need stable network IDs, ordered deployment, and persistent storage per pod.
StatefulSet vs Deployment
AspectDeploymentStatefulSet
Pod NamesRandom (catalog-7d9f8b-x2k4j)Ordered (postgres-0, postgres-1)
Creation OrderParallelSequential (0 → 1 → 2)
Deletion OrderRandomReverse (2 → 1 → 0)
StorageShared PVCPer-pod PVC
Network IDChanges on restartStable DNS per pod
StatefulSet Manifest
STATEFULSET.YAMLapiVersion: apps/v1 kind: StatefulSet metadata: name: postgres spec: serviceName: postgres-headless replicas: 3 selector: matchLabels: app: postgres template: metadata: labels: app: postgres spec: containers: - name: postgres image: postgres:15 ports: - containerPort: 5432 volumeMounts: - name: data mountPath: /var/lib/postgresql/data volumeClaimTemplates: - metadata: name: data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi
Headless Service
HEADLESS.YAMLapiVersion: v1 kind: Service metadata: name: postgres-headless spec: clusterIP: None selector: app: postgres ports: - port: 5432
Headless service (clusterIP: None) creates DNS entries for each pod: postgres-0.postgres-headless.default.svc.cluster.local
11🔧

ConfigMaps & Secrets

Configuration Management

ConfigMaps store non-sensitive configuration data. Secrets store sensitive data like passwords and API keys. Both decouple configuration from container images, enabling the same image across environments.
ConfigMap
CONFIGMAP.YAMLapiVersion: v1 kind: ConfigMap metadata: name: app-config data: DATABASE_HOST: "postgres-headless" LOG_LEVEL: "info" config.yaml: | server: port: 8080 cache: ttl: 3600
Secret
SECRET.YAMLapiVersion: v1 kind: Secret metadata: name: db-credentials type: Opaque data: username: YWRtaW4= # base64 encoded password: cGFzc3dvcmQxMjM= # base64 encoded
Using in Pods
POD-CONFIG.YAMLapiVersion: v1 kind: Pod metadata: name: api-server spec: containers: - name: api image: myregistry/api:v1 envFrom: - configMapRef: name: app-config env: - name: DB_PASSWORD valueFrom: secretKeyRef: name: db-credentials key: password volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: name: app-config
$ echo -n "mypassword" | base64Encode value for Secret
$ kubectl create secret generic db-creds --from-literal=password=mypasswordCreate Secret from literal
$ kubectl create configmap app-cfg --from-file=config.yamlCreate ConfigMap from file
⚠️ Important

Secrets are base64 encoded, not encrypted! Anyone with cluster access can decode them. Use external secret managers (Vault, AWS Secrets Manager) for production.

12🩺

Health Probes

Liveness, Readiness & Startup

By default, Kubernetes only checks if the main process is running. Probes let you define custom health checks — detect deadlocks, verify dependencies, and handle slow startups.
Three Probe Types
💓
Liveness
Is container alive? Failure → restart. Detect deadlocks.
Readiness
Ready for traffic? Failure → remove from service. Warmup checks.
🚀
Startup
Has startup completed? Disables other probes until success.
Probe Example
PROBES.YAMLapiVersion: v1 kind: Pod metadata: name: order-service spec: containers: - name: api image: myregistry/order-api:v2 ports: - containerPort: 8080 startupProbe: httpGet: path: /health/startup port: 8080 failureThreshold: 30 periodSeconds: 10 livenessProbe: httpGet: path: /health/live port: 8080 periodSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: path: /health/ready port: 8080 periodSeconds: 5 failureThreshold: 3
Probe Mechanisms
MechanismSuccess ConditionBest For
httpGetHTTP 2xx-3xx responseWeb services
execCommand exit code 0Custom scripts
tcpSocketTCP connection succeedsDatabases
grpcgRPC health checkgRPC services
⚠️ Important

Liveness probes should NEVER check external dependencies. A database outage shouldn't restart your app — it should stop receiving traffic (readiness).

13📊

Resource Management

Requests, Limits & QoS

Without resource specs, pods can consume unlimited CPU/memory, starving other workloads. Requests guarantee minimum resources for scheduling. Limits cap maximum usage.
Requests vs Limits
RequestsLimits
PurposeMinimum guaranteedMaximum allowed
SchedulingUsed by schedulerNot considered
CPU ExceededN/AThrottled
Memory ExceededN/AOOMKilled
Resource Specification
RESOURCES.YAMLresources: requests: memory: "256Mi" cpu: "250m" # 0.25 CPU cores limits: memory: "512Mi" cpu: "500m" # 0.5 CPU cores
QoS Classes
ClassConditionEviction Priority
Guaranteedrequests == limitsLast
BurstableAt least one request/limitMiddle
BestEffortNo requests or limitsFirst
$ kubectl top podsView pod resource usage
$ kubectl describe nodeView node allocatable resources
⚡ Pro Tip

Start with requests = typical usage, limits = 2-3x requests. Monitor actual usage with kubectl top and adjust based on real data.

14📍

Advanced Scheduling

Affinity, Taints & Tolerations

By default, the scheduler places pods optimally. For specific requirements — SSD nodes, co-location, dedicated node pools — use node selectors, affinity rules, and taints/tolerations.
Scheduling Mechanisms
MechanismPurpose
nodeSelectorSimple label matching
Node AffinityAdvanced selection with operators
Pod AffinityCo-locate with other pods
Pod Anti-AffinitySpread away from pods
Taints/TolerationsRepel pods from nodes
Node Selector
NODESELECTOR.YAMLspec: nodeSelector: disk: ssd gpu: "true"
Node Affinity
AFFINITY.YAMLaffinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: zone operator: In values: [us-east-1a, us-east-1b]
Taints & Tolerations
$ kubectl taint nodes gpu-node dedicated=gpu:NoScheduleAdd taint
$ kubectl taint nodes gpu-node dedicated=gpu:NoSchedule-Remove taint
TOLERATION.YAMLtolerations: - key: "dedicated" operator: "Equal" value: "gpu" effect: "NoSchedule"
⚡ Pro Tip

Use pod anti-affinity with topologyKey: kubernetes.io/hostname to spread replicas across nodes for high availability.

15🔐

RBAC Security

Role-Based Access Control

By default, anyone with cluster access can do anything. RBAC defines who (subjects) can perform what actions (verbs) on which resources. Essential for multi-tenant clusters and compliance.
RBAC Components
👤
Subjects
Who: Users, Groups, ServiceAccounts
📋
Roles
What: Permissions (verbs + resources)
🔗
Bindings
Connect subjects to roles
Role vs ClusterRole
TypeScope
Role + RoleBindingSingle namespace
ClusterRole + ClusterRoleBindingEntire cluster
Role Example
ROLE.YAMLapiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: development name: pod-reader rules: - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list", "watch"]
RoleBinding
ROLEBINDING.YAMLapiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: dev-pod-reader namespace: development subjects: - kind: User name: alice apiGroup: rbac.authorization.k8s.io - kind: ServiceAccount name: monitoring namespace: monitoring roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
Testing Permissions
$ kubectl auth can-i create podsCheck current user permission
$ kubectl auth can-i delete pods --as=aliceCheck as another user
$ kubectl auth can-i --listList all permissions
Follow least privilege — grant minimum permissions needed
Never use cluster-admin for applications
Avoid wildcards (*) in verbs and resources
Use namespaces to isolate teams
Structured Learning
Learning Paths
Curated sequences from beginner to production-ready engineer.
🐳
Docker Foundations
First Dockerfile to multi-stage production builds and Compose orchestration.
8 articlesBeginner → Intermediate
☸️
Kubernetes Mastery
Multi-zone production clusters, networking, storage, RBAC, and GitOps.
12 articlesIntermediate → Advanced
🏗️
Infrastructure as Code
Terraform + Ansible end-to-end. Provision cloud resources and automate config.
10 articlesIntermediate
⚙️
CI/CD Engineering
Jenkins, GitHub Actions, ArgoCD — zero-downtime deployments and automated testing.
9 articlesIntermediate → Advanced
Built by practitioners,
for practitioners.
We're engineers who build and run DevOps infrastructure daily. We write the guides we wish we had.
🎯
Our Mission
Make production-grade DevOps knowledge accessible to every engineer, whether you're moving into platform engineering or embracing cloud-native tools for the first time.
🔬
Our Approach
Every tutorial includes a real architecture diagram, tested commands, and explanations of why — not just how. We cover failure modes, not just the happy path.
🚀
What's Next
Platform Engineering, GitOps with ArgoCD, eBPF observability, FinOps, and MLOps pipelines. Subscribe on YouTube for every new release.
👥
Community
Join 10,000+ engineers on YouTube and Instagram. We answer every question, every time. Real engineers helping real engineers.
Get In Touch
Contact Us
Questions, content ideas, or partnership enquiries.
📞
Phone · Mon–Sat 10am–7pm IST
+91 70364 41388

Privacy Policy

Data We Collect

Name, email, and mobile number on registration. Passwords stored using Argon2id hashing — never plaintext. OTPs cleared immediately after use.

How We Use It

Authentication and personalising your experience only. Never sold or shared with third parties.

Security

HTTPS everywhere. HttpOnly + Secure + SameSite=Strict cookies. CSRF tokens on all POST actions.

Cookies

One session cookie for authentication. No tracking or advertising cookies.

Contact

Email bsuresh@devopsclicks.com for data deletion or privacy concerns.

Terms & Conditions

Usage

Content is for personal learning only. Commercial redistribution requires written consent.

Accuracy

Always verify commands against official documentation before production use.

Account

Keep credentials secure. DevOpsClicks is not liable for unauthorized access from user negligence.

Changes

Terms may update at any time. Continued use constitutes acceptance.