🐳 Docker & ☸️ Kubernetes

← Back to Cheatsheets

Docker packages applications into portable containers β€” isolated environments that run the same everywhere. Kubernetes orchestrates those containers at scale, handling scheduling, scaling, self-healing, and networking across a cluster of machines.

Docker: Image β†’ Container (single host) Kubernetes: Pod β†’ Deployment β†’ Service (cluster) Runtime: containerd / runc
Docker and Kubernetes architecture diagram
Resources: Docker CLI Docker Compose Docker Hub Dockerfile guide | kubectl reference K8s concepts Declarative config
🐳 Docker

Images

β–Ό

Images are immutable snapshots built from a Dockerfile. Each RUN, COPY, and ADD instruction creates a new layer β€” layers are cached, so order matters for build speed.

Pull / Push
docker pull nginx:alpine
docker push myuser/myimage:1.0
Build from Dockerfile
docker build -t myimage:latest .
docker build -t myimage:latest -f Dockerfile.prod .
-t sets the name:tag; -f specifies a non-default Dockerfile
Tag an Image
docker tag myimage:latest myuser/myimage:1.0
List / Remove Images
docker images
docker rmi myimage:latest
Minimal Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Containers

β–Ό

Containers are running instances of an image. They are ephemeral by default β€” any filesystem changes are lost when the container is removed. Use volumes to persist data.

Run a Container
docker run -d -p 8080:80 --name web nginx
docker run -it --rm ubuntu bash        # interactive, auto-remove on exit
docker run -e ENV_VAR=value myimage    # set environment variable
-d = detached/background, -p = host:container port, -it = interactive TTY
List Containers
docker ps
docker ps -a   # includes stopped containers
Start / Stop / Restart
docker start web
docker stop web
docker restart web
Execute Command Inside Container
docker exec -it web bash
docker exec web ls /app
View Logs
docker logs web
docker logs -f web          # follow live
docker logs --tail 100 web  # last 100 lines
Copy Files To / From Container
docker cp ./local.txt web:/app/local.txt
docker cp web:/app/output.txt ./output.txt
Inspect a Container
docker inspect web
Returns full JSON config β€” IP, mounts, env vars, etc.

Volumes

β–Ό

Volumes persist data outside the container lifecycle. Named volumes are managed by Docker; bind mounts map a host path directly into the container.

Named Volume
docker volume create mydata
docker run -v mydata:/app/data myimage
docker volume ls
docker volume rm mydata
Bind Mount (Host Path)
docker run -v /host/path:/container/path myimage
docker run -v $(pwd):/app myimage   # mount current dir
Bind mounts reflect live changes β€” useful for development.

Networking

β–Ό

Containers on the same network can communicate by container name. The default bridge network doesn't support DNS; create a custom network instead.

Create and Use a Network
docker network create mynet
docker run --network mynet --name db postgres
docker run --network mynet --name app myimage  # can reach "db" by name
List / Inspect / Remove
docker network ls
docker network inspect mynet
docker network rm mynet

Docker Compose

β–Ό

Compose defines multi-container applications in a docker-compose.yml file. It handles networking, volumes, and startup order automatically.

Common Compose Commands
docker compose up -d         # start in background
docker compose down          # stop and remove containers
docker compose down -v       # also remove volumes
docker compose build         # rebuild images
docker compose ps            # list services
docker compose logs -f       # follow all service logs
docker compose exec app bash # shell into a service
Example docker-compose.yml
services:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://postgres:secret@db/mydb
    depends_on:
      - db

volumes:
  pgdata:

Cleanup

β–Ό

Docker accumulates stopped containers, dangling images, and unused volumes over time. Use prune commands to reclaim disk space.

Prune by Type
docker container prune   # remove stopped containers
docker image prune       # remove dangling (untagged) images
docker volume prune      # remove unused volumes
docker network prune     # remove unused networks
Remove Everything Unused at Once
docker system prune -a --volumes
Removes all stopped containers, unused images, volumes, and networks β€” use with care.
Check Disk Usage
docker system df
☸️ Kubernetes

Architecture

β–Ό

A Kubernetes cluster has a control plane (API Server, scheduler, etcd, controller-manager) and one or more worker nodes. Each node runs a kubelet agent and a container runtime. Workloads are scheduled as Pods β€” the smallest deployable unit, containing one or more containers.

Control Plane Components
  • kube-apiserver β€” front door for all API calls
  • etcd β€” cluster state store (key-value)
  • kube-scheduler β€” assigns pods to nodes
  • kube-controller-manager β€” reconciliation loops
Node Components
  • kubelet β€” ensures containers in pods are running
  • kube-proxy β€” network rules for Service routing
  • container runtime β€” containerd / CRI-O
Key Resource Hierarchy
Cluster β†’ Namespace β†’ Deployment β†’ ReplicaSet β†’ Pod β†’ Container

kubectl

β–Ό

The Kubernetes CLI. All commands talk to the API server via your ~/.kube/config file. Most commands accept -n <namespace> or -A (all namespaces).

Get Resources
kubectl get pods
kubectl get pods -n mynamespace
kubectl get pods -A                  # all namespaces
kubectl get deployments,services
kubectl get all                      # pods, deploys, svcs, etc.
kubectl get pod mypod -o wide        # extra columns (node, IP)
kubectl get pod mypod -o yaml        # full manifest
Describe & Debug
kubectl describe pod mypod
kubectl describe node mynode
kubectl logs mypod
kubectl logs -f mypod                # follow
kubectl logs mypod -c mycontainer    # specific container
kubectl events --for pod/mypod
Apply & Delete
kubectl apply -f manifest.yaml
kubectl apply -f ./k8s/             # apply a whole directory
kubectl delete -f manifest.yaml
kubectl delete pod mypod
kubectl delete pod mypod --grace-period=0  # force
Exec & Port-Forward
kubectl exec -it mypod -- bash
kubectl exec -it mypod -c mycontainer -- sh
kubectl port-forward pod/mypod 8080:80
kubectl port-forward svc/myservice 8080:80
Context & Namespace Switching
kubectl config get-contexts               # list all contexts
kubectl config use-context mycontext      # switch cluster
kubectl config current-context
kubectl config set-context --current --namespace=mynamespace  # set default ns

Workloads β€” Pods & Deployments

β–Ό

A Pod is one or more containers sharing network and storage. A Deployment manages a ReplicaSet to ensure the desired number of pod replicas are running. Never create bare Pods in production β€” use a Deployment so pods are rescheduled if a node fails.

Pod Manifest
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    resources:
      requests:
        memory: "64Mi"
        cpu: "100m"
      limits:
        memory: "128Mi"
        cpu: "250m"
Deployment Manifest
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myimage:1.0
        ports:
        - containerPort: 3000
        env:
        - name: ENV_VAR
          value: "value"
Scale, Rollout & Rollback
kubectl scale deployment myapp --replicas=5
kubectl set image deployment/myapp myapp=myimage:2.0  # rolling update
kubectl rollout status deployment/myapp
kubectl rollout history deployment/myapp
kubectl rollout undo deployment/myapp              # revert to previous
kubectl rollout undo deployment/myapp --to-revision=2

Services & Networking

β–Ό

A Service gives pods a stable DNS name and IP, load-balancing traffic across matching pods via label selectors. Pod IPs change on reschedule β€” always access pods through a Service.

Service Types
  • ClusterIPInternal only β€” default. Reachable within the cluster as svcname.namespace.svc.cluster.local.
  • NodePortExposes on each node's IP at a static port (30000–32767). OK for dev; not production.
  • LoadBalancerProvisions a cloud load balancer (AWS ELB, GCP LB, etc.). Production-grade external access.
Service Manifest
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
spec:
  selector:
    app: myapp          # matches pod labels
  ports:
  - port: 80            # service port
    targetPort: 3000    # container port
  type: ClusterIP       # or NodePort / LoadBalancer
Ingress (HTTP routing)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-svc
            port:
              number: 80
Requires an Ingress controller (nginx-ingress, traefik, etc.) to be installed in the cluster.

ConfigMaps & Secrets

β–Ό

ConfigMaps store non-sensitive config as key-value pairs. Secrets store sensitive data (base64-encoded by default β€” use encryption at rest in production). Both can be injected as environment variables or mounted as files.

Create
# ConfigMap
kubectl create configmap myconfig \
  --from-literal=LOG_LEVEL=info \
  --from-file=config.properties

# Secret
kubectl create secret generic mysecret \
  --from-literal=DB_PASSWORD=s3cr3t \
  --from-literal=API_KEY=abc123
Reference in a Pod
spec:
  containers:
  - name: myapp
    image: myimage:1.0
    env:
    - name: LOG_LEVEL
      valueFrom:
        configMapKeyRef:
          name: myconfig
          key: LOG_LEVEL
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: DB_PASSWORD
    envFrom:
    - configMapRef:
        name: myconfig  # inject all keys at once
Mount as Files
spec:
  volumes:
  - name: config-vol
    configMap:
      name: myconfig
  containers:
  - name: myapp
    volumeMounts:
    - name: config-vol
      mountPath: /etc/config   # each key becomes a file

Namespaces

β–Ό

Namespaces provide logical isolation within a cluster β€” separate environments (dev/staging/prod), teams, or applications. Resources in different namespaces can still communicate via fully-qualified DNS: svcname.namespace.svc.cluster.local.

Namespace Commands
kubectl get namespaces
kubectl create namespace staging
kubectl delete namespace staging

# Run everything in a namespace
kubectl -n staging get pods
kubectl -n staging apply -f deploy.yaml

# Set your default namespace for the session
kubectl config set-context --current \
  --namespace=staging
Namespace Manifest + Resource Quota
apiVersion: v1
kind: Namespace
metadata:
  name: staging
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: staging-quota
  namespace: staging
spec:
  hard:
    pods: "20"
    requests.cpu: "4"
    requests.memory: 4Gi
    limits.cpu: "8"
    limits.memory: 8Gi
Default Namespaces
default

Where resources land if no namespace is specified

kube-system

Control plane components, DNS, networking add-ons

kube-public

Publicly readable; rarely used directly

kube-node-lease

Node heartbeat lease objects