Docker and Kubernetes Interview Questions (2025)

Docker and Kubernetes questions appear in backend, DevOps, platform engineering, and SRE interviews. Interviewers expect you to understand containers at a practical level — not just commands, but how namespaces and cgroups work, how Kubernetes schedules pods, and how to debug a broken deployment.

Docker Fundamentals

What is the difference between a container and a virtual machine?

Dimension Container Virtual Machine
Isolation Process + namespace isolation (shares host kernel) Full OS isolation (separate kernel)
Startup time Milliseconds Seconds to minutes
Overhead Minimal (no guest OS) Significant (full OS per VM)
Security boundary Weaker — kernel shared, container escapes possible Stronger — hypervisor boundary
Portability Image includes app + deps, runs anywhere Docker runs VM image is GB-sized and hypervisor-specific

Containers use Linux kernel features: namespaces (isolate PID, network, filesystem, user IDs) and cgroups (limit CPU, memory, I/O). A container is just a process with restricted visibility.

What is a Docker image vs a container?

An image is a read-only, layered template. A container is a running instance of an image — an image with a writable layer on top. Multiple containers can run from the same image simultaneously, each with its own writable layer.

# Images are built from Dockerfiles layer by layer
# Each RUN/COPY/ADD instruction adds a layer
# Layers are cached — unchanged layers are reused

FROM node:20-alpine          # base layer
WORKDIR /app
COPY package*.json ./        # layer 2
RUN npm ci --only=production # layer 3 — cached if package.json unchanged
COPY . .                     # layer 4
EXPOSE 3000
CMD ["node", "server.js"]

What is the difference between CMD and ENTRYPOINT?

# CMD: default command, easily overridden at docker run
CMD ["node", "server.js"]
# docker run myimage python script.py   # overrides CMD

# ENTRYPOINT: always runs, CMD becomes default arguments
ENTRYPOINT ["node"]
CMD ["server.js"]
# docker run myimage other.js           # runs: node other.js

# Best practice: ENTRYPOINT for the binary, CMD for default args
# This makes the container behave like an executable

What is a multi-stage build and why use it?

# Stage 1: build (heavy — includes compilers, test frameworks)
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server .

# Stage 2: runtime (minimal — only the binary)
FROM scratch                   # empty base image: ~0 bytes
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]

# Result: production image is ~5MB instead of ~1GB
# No build tools, no source code, smaller attack surface

Kubernetes Fundamentals

What are the core Kubernetes objects?

Object What it does
Pod Smallest deployable unit — one or more containers sharing network and storage
Deployment Manages a ReplicaSet, handles rolling updates and rollbacks
Service Stable network endpoint (ClusterIP, NodePort, LoadBalancer) for a set of pods
ConfigMap Non-secret configuration data injected as env vars or files
Secret Base64-encoded sensitive data (passwords, tokens)
Ingress HTTP/HTTPS routing rules from outside the cluster to services
PersistentVolume Cluster-level storage resource (EBS, NFS, etc.)
Namespace Virtual cluster — isolates resources by team, env, or project

What is the difference between a Deployment and a StatefulSet?

Deployment: for stateless apps. Pods are interchangeable — any pod can be killed and replaced. Pod names are random (my-app-6b7f9d-xyz). Scales up/down freely, rolling updates replace old pods with new ones.

StatefulSet: for stateful apps (databases, Kafka, Zookeeper). Pods have stable identities (my-app-0, my-app-1, my-app-2), stable hostnames, and each gets its own PersistentVolumeClaim. Scales and updates in order. Use for anything that needs stable storage identity or peer-to-peer communication between specific instances.

How does Kubernetes scheduling work?

# Scheduler finds a node for each pending pod via 2 phases:
#
# Phase 1 — Filtering: eliminate nodes that cannot run the pod
#   - Node has enough CPU/memory (requests, not limits)
#   - Node satisfies nodeSelector and affinity rules
#   - Taints/tolerations match
#   - PersistentVolumes available in the same zone
#
# Phase 2 — Scoring: rank remaining nodes
#   - LeastRequestedPriority: prefer nodes with most free resources
#   - BalancedResourceAllocation: even CPU vs memory usage
#   - PodTopologySpread: spread pods across zones/nodes

# Resource requests vs limits (critical interview topic)
resources:
  requests:               # used by scheduler to find a node
    memory: "256Mi"       # guaranteed minimum
    cpu: "250m"           # 0.25 CPU cores
  limits:                 # enforced at runtime
    memory: "512Mi"       # OOMKilled if exceeded
    cpu: "1000m"          # throttled (not killed) if exceeded

What is the difference between requests and limits?

Requests are what the scheduler uses to place the pod — a node must have at least this much free. They are a guaranteed minimum. Limits are enforced at runtime: CPU is throttled (never killed) if the container exceeds its limit; memory causes OOMKill if exceeded. Setting limits too low causes throttling and OOMKills. Setting no limits allows one pod to consume all node resources (noisy neighbor). Best practice: always set requests and limits; set memory limit = memory request for predictable behavior; allow some CPU burst by setting CPU limit higher than request.

Services and Networking

# Service types
ClusterIP:    default. Only reachable within the cluster.
              Use for internal microservice-to-microservice communication.

NodePort:     exposes on a port on every node (30000-32767).
              Use for dev/testing; not for production.

LoadBalancer: provisions a cloud load balancer (ELB, NLB on AWS).
              Each service gets its own LB — expensive at scale.

Ingress:      single entry point for HTTP/HTTPS traffic.
              Routes to different services based on hostname/path rules.
              Much cheaper than one LoadBalancer per service.

# Ingress example
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: api.myapp.com
    http:
      paths:
      - path: /users
        pathType: Prefix
        backend:
          service:
            name: user-service
            port: { number: 80 }
      - path: /orders
        pathType: Prefix
        backend:
          service:
            name: order-service
            port: { number: 80 }

Rolling Updates and Zero-Downtime Deployments

apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2          # allow 12 pods during update (10 + 2)
      maxUnavailable: 1    # minimum 9 pods must be ready at all times

  # Readiness probe: pod only receives traffic when ready
  readinessProbe:
    httpGet:
      path: /health/ready
      port: 8080
    initialDelaySeconds: 10
    periodSeconds: 5
    failureThreshold: 3

  # Liveness probe: restart pod if stuck
  livenessProbe:
    httpGet:
      path: /health/live
      port: 8080
    periodSeconds: 10
    failureThreshold: 5

Readiness vs Liveness: Readiness controls traffic routing — a pod fails readiness when it is starting up or temporarily overloaded, removing it from service endpoints without restarting it. Liveness detects deadlocks — a pod fails liveness when it cannot recover, triggering a restart.

Common Debugging Commands

# View pod status and events
kubectl get pods -n my-namespace
kubectl describe pod my-pod-xyz -n my-namespace
# Look for: Events section at the bottom — shows OOMKill, pull errors, etc.

# View logs
kubectl logs my-pod-xyz -n my-namespace
kubectl logs my-pod-xyz -n my-namespace -c my-container  # specific container
kubectl logs my-pod-xyz --previous  # logs from previous (crashed) container

# Debug a running pod
kubectl exec -it my-pod-xyz -- sh

# Check resource usage
kubectl top pods -n my-namespace
kubectl top nodes

# Check why a pod is Pending (common: insufficient resources, unschedulable)
kubectl describe pod my-pending-pod | grep -A 20 Events

# Force restart all pods in a deployment (rolling)
kubectl rollout restart deployment/my-deployment

# Check rollout status
kubectl rollout status deployment/my-deployment

# Roll back to previous version
kubectl rollout undo deployment/my-deployment

Interview Discussion Points

  • What happens when a node goes down? The node controller marks pods as Unknown after 5 minutes; Deployment controller creates replacement pods on healthy nodes. StatefulSets do not automatically reschedule to prevent split-brain
  • How do you handle secrets? Store in Kubernetes Secrets (base64, not encrypted at rest by default) + enable etcd encryption, or use external secrets managers (Vault, AWS Secrets Manager) with the External Secrets Operator
  • How do you prevent one team from affecting another? Namespaces + ResourceQuotas (limit total CPU/memory per namespace) + NetworkPolicies (restrict pod-to-pod traffic)
  • What is a DaemonSet? Runs one pod per node — used for log collectors (Fluentd), node monitoring agents, node-level network plugins

Frequently Asked Questions

What is the difference between a container and a virtual machine?

A container shares the host OS kernel but uses Linux namespaces (PID, network, filesystem, user) and cgroups (CPU, memory limits) to isolate processes. A virtual machine runs a complete guest OS on top of a hypervisor — full kernel isolation, stronger security boundary, but much heavier (GB-size images, seconds to boot, significant memory overhead). Containers start in milliseconds, share the kernel efficiently, and package only the app and its dependencies. The tradeoff: containers have a weaker security boundary (kernel vulnerabilities affect all containers on the host), while VMs are isolated at the hardware level.

What is the difference between Kubernetes requests and limits?

Requests are what the Kubernetes scheduler uses to find a node: the node must have at least this much free CPU and memory. Requests are a guaranteed minimum that the container will always have available. Limits are enforced at runtime: if a container exceeds its memory limit, it is OOMKilled (killed by the out-of-memory handler); if it exceeds its CPU limit, it is throttled (slowed down, not killed). Always set both: requests too low causes pods to be scheduled on overloaded nodes; limits too low causes unnecessary OOMKills and CPU throttling. Best practice: set memory limit equal to request (predictable behavior), and allow CPU burst by setting the limit higher than the request.

What is the difference between a Deployment and a StatefulSet in Kubernetes?

A Deployment manages stateless pods — each pod is interchangeable and can be killed and replaced freely. Pods get random names (my-app-6b7f9d-xyz), and any pod can serve any request. A StatefulSet manages stateful applications that need stable identity: pods get ordered, persistent names (my-app-0, my-app-1), stable DNS hostnames, and each gets its own PersistentVolumeClaim that survives pod restarts. StatefulSets scale and update in order (0 first, then 1, then 2) to respect quorum requirements. Use StatefulSets for databases, Kafka brokers, Zookeeper, or any application where instance identity matters.

{
“@context”: “https://schema.org”,
“@type”: “FAQPage”,
“mainEntity”: [
{
“@type”: “Question”,
“name”: “What is the difference between a container and a virtual machine?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “A container shares the host OS kernel but uses Linux namespaces (PID, network, filesystem, user) and cgroups (CPU, memory limits) to isolate processes. A virtual machine runs a complete guest OS on top of a hypervisor — full kernel isolation, stronger security boundary, but much heavier (GB-size images, seconds to boot, significant memory overhead). Containers start in milliseconds, share the kernel efficiently, and package only the app and its dependencies. The tradeoff: containers have a weaker security boundary (kernel vulnerabilities affect all containers on the host), while VMs are isolated at the hardware level.”
}
},
{
“@type”: “Question”,
“name”: “What is the difference between Kubernetes requests and limits?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Requests are what the Kubernetes scheduler uses to find a node: the node must have at least this much free CPU and memory. Requests are a guaranteed minimum that the container will always have available. Limits are enforced at runtime: if a container exceeds its memory limit, it is OOMKilled (killed by the out-of-memory handler); if it exceeds its CPU limit, it is throttled (slowed down, not killed). Always set both: requests too low causes pods to be scheduled on overloaded nodes; limits too low causes unnecessary OOMKills and CPU throttling. Best practice: set memory limit equal to request (predictable behavior), and allow CPU burst by setting the limit higher than the request.”
}
},
{
“@type”: “Question”,
“name”: “What is the difference between a Deployment and a StatefulSet in Kubernetes?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “A Deployment manages stateless pods — each pod is interchangeable and can be killed and replaced freely. Pods get random names (my-app-6b7f9d-xyz), and any pod can serve any request. A StatefulSet manages stateful applications that need stable identity: pods get ordered, persistent names (my-app-0, my-app-1), stable DNS hostnames, and each gets its own PersistentVolumeClaim that survives pod restarts. StatefulSets scale and update in order (0 first, then 1, then 2) to respect quorum requirements. Use StatefulSets for databases, Kafka brokers, Zookeeper, or any application where instance identity matters.”
}
}
]
}

Scroll to Top