Containers & Orchestration
Understanding Docker, Kubernetes and modern containerisation technologies
Last updated: 8/15/2025
Master the art of packaging, deploying and managing applications using containers - the building blocks of modern cloud infrastructure.
What are Containers?
The Core Concept
Portable packages for applications
A container is like a shipping container for software. Just as shipping containers can be moved between trucks, ships and trains without unpacking, software containers can run on any system that supports containers.
Real-world analogy: Think of containers like food trucks. Each truck (container) has everything it needs to operate - kitchen equipment, ingredients, power supply - and can set up shop anywhere there's a parking space (host system).
Containers vs Virtual Machines
Understanding the Difference
Lightweight isolation
Traditional VMs:
┌─────────────────────────────────────┐
│ Virtual Machine 1 │
│ ┌─────────────────────────────┐ │
│ │ Guest OS (10GB+) │ │
│ │ ┌───────────────────────┐ │ │
│ │ │ Application │ │ │
│ │ └───────────────────────┘ │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
Containers:
┌─────────────────────────────────────┐
│ Container 1 (MB) │
│ ┌───────────────────────┐ │
│ │ Application │ │
│ │ + Dependencies │ │
│ └───────────────────────┘ │
│ Shared OS Kernel │
└─────────────────────────────────────┘
Key differences:
- Size: Containers are MBs, VMs are GBs
- Startup: Containers start in seconds, VMs in minutes
- Resource usage: Containers share OS kernel, VMs need full OS
- Isolation: VMs offer stronger isolation, containers are lighter
Docker Fundamentals
Docker Architecture
The container ecosystem
Core components:
- Docker Engine: The runtime that creates and manages containers
- Images: Read-only templates for creating containers
- Containers: Running instances of images
- Registry: Storage for Docker images (like Docker Hub)
Dockerfile
The recipe for building images
# Start from a base image
FROM node:18-alpine
# Set working directory
WORKDIR /app
# Copy dependency files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY . .
# Expose port
EXPOSE 3000
# Define startup command
CMD ["node", "server.js"]
Essential Docker Commands
# Build an image
docker build -t myapp:1.0 .
# Run a container
docker run -d -p 3000:3000 myapp:1.0
# List running containers
docker ps
# View logs
docker logs container_id
# Stop a container
docker stop container_id
# Remove a container
docker rm container_id
Container Images
Image Layers
Building blocks of efficiency
Docker images are built in layers, each representing a change from the previous layer. This makes images efficient and cacheable.
FROM ubuntu:22.04 # Layer 1: Base OS
RUN apt-get update # Layer 2: Update packages
RUN apt-get install -y # Layer 3: Install dependencies
COPY app /app # Layer 4: Add application
CMD ["./app"] # Layer 5: Set command
Benefits:
- Shared layers between images save space
- Faster builds through layer caching
- Easy to track changes
Multi-stage Builds
Optimising image size
# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]
Result: Smaller production images without build tools
Container Registries
Docker Hub
The default public registry
The GitHub of Docker images - store, share and discover container images.
# Push to Docker Hub
docker tag myapp:1.0 username/myapp:1.0
docker push username/myapp:1.0
# Pull from Docker Hub
docker pull nginx:latest
Private Registries
Secure image storage
Options:
- Amazon ECR: AWS's container registry
- Google Container Registry: GCP's offering
- Azure Container Registry: Microsoft's solution
- GitHub Container Registry: Integrated with GitHub
- Self-hosted: Run your own registry
Kubernetes (K8s)
What is Kubernetes?
Container orchestration at scale
Kubernetes is like a conductor for an orchestra of containers. It manages where containers run, ensures they stay healthy and coordinates communication between them.
Core benefits:
- Automatic scaling
- Self-healing
- Load balancing
- Rolling updates
- Secret management
Kubernetes Architecture
┌─────────────────────────────────────────┐
│ Control Plane │
│ ┌──────────┐ ┌──────────┐ │
│ │ API │ │Scheduler │ │
│ │ Server │ │ │ │
│ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ │
│ │Controller│ │ etcd │ │
│ │ Manager │ │(Database)│ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────────┘
│
┌─────────────────────────────────────────┐
│ Worker Nodes │
│ ┌─────────────────────────────┐ │
│ │ Node 1 │ │
│ │ ┌──────┐ ┌──────┐ │ │
│ │ │ Pod │ │ Pod │ │ │
│ │ └──────┘ └──────┘ │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────────┘
Key Kubernetes Concepts
Pods
The smallest deployable unit
A Pod wraps one or more containers that share storage and network.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: myapp
image: myapp:1.0
ports:
- containerPort: 3000
Deployments
Managing replica sets
Deployments ensure a specified number of pod replicas are running.
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0
ports:
- containerPort: 3000
Services
Networking and load balancing
Services provide stable network endpoints for pods.
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
Container Orchestration Platforms
Managed Kubernetes
Amazon EKS (Elastic Kubernetes Service)
- Fully managed control plane
- Deep AWS integration
- Auto-scaling with Fargate
Google GKE (Google Kubernetes Engine)
- Autopilot mode for hands-off management
- Best-in-class Kubernetes experience
- Integrated with Google Cloud services
Azure AKS (Azure Kubernetes Service)
- Integrated with Azure Active Directory
- Azure Policy for governance
- Dev Spaces for development
Simpler Alternatives
Amazon ECS (Elastic Container Service)
- AWS-native orchestration
- Simpler than Kubernetes
- Tight AWS integration
Docker Swarm
- Built into Docker
- Easier learning curve
- Good for smaller deployments
Nomad
- Lightweight and flexible
- Supports non-container workloads
- Simple architecture
Container Networking
Network Types
Bridge Network
- Default network for containers
- Containers can communicate on same host
Host Network
- Container uses host's network directly
- Better performance, less isolation
Overlay Network
- Spans multiple Docker hosts
- Used in Swarm and Kubernetes
Service Mesh
Advanced networking for microservices
Service meshes like Istio or Linkerd provide:
- Traffic management
- Security (mTLS)
- Observability
- Policy enforcement
Container Storage
Volume Types
Ephemeral Storage
- Deleted when container stops
- Good for temporary data
Persistent Volumes
- Survives container restarts
- Essential for databases
# Kubernetes Persistent Volume Claim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: database-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Storage Solutions
- CSI (Container Storage Interface): Standard for storage plugins
- Rook: Cloud-native storage for Kubernetes
- Longhorn: Distributed block storage
- GlusterFS: Distributed file system
Security Best Practices
Image Security
Scan for vulnerabilities:
# Using Trivy
trivy image myapp:1.0
# Using Snyk
snyk container test myapp:1.0
Use minimal base images:
# Good: Alpine-based
FROM node:18-alpine
# Better: Distroless
FROM gcr.io/distroless/nodejs18
Runtime Security
Run as non-root:
USER node
Read-only filesystem:
securityContext:
readOnlyRootFilesystem: true
Network policies:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-netpol
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
Monitoring and Logging
Container Metrics
Prometheus + Grafana
- Industry standard for metrics
- Beautiful dashboards
- Alerting capabilities
Key metrics to monitor:
- CPU and memory usage
- Network I/O
- Disk usage
- Application-specific metrics
Centralised Logging
ELK Stack (Elasticsearch, Logstash, Kibana)
- Powerful log aggregation
- Full-text search
- Visualisation
Fluentd/Fluent Bit
- Lightweight log forwarding
- Multiple output plugins
- Kubernetes-native
CI/CD with Containers
Build Pipeline
# GitHub Actions example
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Push to registry
run: |
docker tag myapp:${{ github.sha }} myregistry/myapp:latest
docker push myregistry/myapp:latest
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/myapp myapp=myregistry/myapp:latest
GitOps
ArgoCD or Flux
- Declarative deployments
- Git as source of truth
- Automatic synchronisation
Development Workflow
Local Development
Docker Compose
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
environment:
- NODE_ENV=development
db:
image: postgres:14
environment:
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Dev Tools
Skaffold
- Continuous development for Kubernetes
- Hot reload for containers
Tilt
- Smart rebuilds and live updates
- Great developer experience
Telepresence
- Develop locally, test in cluster
- Route cluster traffic to local machine
Common Patterns
Sidecar Pattern
Helper containers
spec:
containers:
- name: app
image: myapp:1.0
- name: logging-agent
image: fluentd:latest
Init Containers
Setup before main container
spec:
initContainers:
- name: migration
image: myapp:1.0
command: ['npm', 'run', 'migrate']
containers:
- name: app
image: myapp:1.0
Ambassador Pattern
Proxy for external services
Used for service discovery, load balancing and circuit breaking.
Troubleshooting
Common Issues
Container won't start:
# Check logs
docker logs container_id
# Inspect container
docker inspect container_id
# Debug interactively
docker run -it myapp:1.0 /bin/sh
Kubernetes pod issues:
# Describe pod
kubectl describe pod pod-name
# Get logs
kubectl logs pod-name
# Execute commands in pod
kubectl exec -it pod-name -- /bin/sh
Cost Optimisation
Right-sizing
- Monitor actual resource usage
- Set appropriate resource requests/limits
- Use horizontal pod autoscaling
Spot Instances
- Use spot/preemptible instances for non-critical workloads
- Implement graceful shutdown handling
Image Optimisation
- Use multi-stage builds
- Choose minimal base images
- Remove unnecessary files
Getting Started
Your First Container
Step 1: Install Docker
# macOS/Windows: Download Docker Desktop
# Linux: Install Docker Engine
Step 2: Create a simple app
// app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello from Container!');
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Step 3: Create Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
Step 4: Build and run
docker build -t myapp .
docker run -p 3000:3000 myapp
Summary
Containers have revolutionised how we build, ship and run applications. They provide consistency across environments, enable microservices architectures and form the foundation of modern cloud-native applications.
Key takeaways:
- Containers package applications with dependencies
- Docker makes container creation and management simple
- Kubernetes orchestrates containers at scale
- Proper security and monitoring are essential
- Start simple, grow as needed
The container ecosystem continues to evolve, making it easier to build scalable, resilient applications that run anywhere!