Containers vs VMs
Containers share the host OS kernel for lightweight isolation; VMs emulate full hardware for stronger but heavier isolation.
What is the difference between containers and VMs?
Containers and virtual machines are both isolation technologies but at different layers of the stack. Understanding the difference determines when each is appropriate.
Virtual Machines
A VM runs a complete operating system on top of virtualised hardware managed by a hypervisor (Type-1: VMware ESXi, Hyper-V, KVM; Type-2: VirtualBox, VMware Workstation).
[Hardware]
[Hypervisor]
[Guest OS 1] [Guest OS 2] [Guest OS 3]
[App] [App] [App]
Characteristics:
- Full OS isolation: each VM has its own kernel
- Strong security boundary: VM escape attacks are very rare and severe
- Startup time: 30 seconds - 2 minutes
- Memory overhead: 1-4 GB per VM (for OS)
- Fixed resource allocation (allocated at VM creation)
- Long-lived: typically run for weeks/months
Containers
Containers share the host kernel and use Linux namespaces (process, network, mount, user) and cgroups (resource limits) to isolate processes from each other.
[Hardware]
[Host OS + Kernel]
[Container Runtime (Docker/containerd)]
[Container 1] [Container 2] [Container 3]
[App] [App] [App]
Characteristics:
- Shared kernel: all containers use the host OS kernel
- Weaker security boundary: kernel exploits can affect all containers
- Startup time: milliseconds to seconds
- Memory overhead: 1-10 MB (only app + dependencies, no OS)
- Dynamic resource limits via cgroups
- Short-lived: designed to start/stop frequently
Image Layers
Docker images are built as stacked, read-only layers:
FROM python:3.12-slim # base layer (shared across images)
COPY requirements.txt # layer 2
RUN pip install ... # layer 3
COPY . . # layer 4
Layers are content-addressed and cached. If you change only your app code, only the last layer is rebuilt - the dependencies layer is reused. This makes builds fast and image distribution efficient.
When VMs Still Win
- Security requirements: containers don't provide the same isolation as VMs; regulated industries (financial services, healthcare) often require VM-level isolation
- Different OS per workload: Windows containers exist but many workloads require a specific OS that differs from the host
- Legacy applications: can't be containerised without significant changes
- Persistent workloads: databases, stateful services that run for months
- AWS Lambda / Fargate: these use micro-VMs (Firecracker) under the hood for per-function isolation - you get container simplicity with VM-level security
Container Security
- Containers share the kernel - a kernel vulnerability affects all containers on the host
- Run containers as non-root users
- Use read-only root filesystems
- Scan images for CVEs (Trivy, Snyk, ECR scanning)
- Use namespaces + seccomp profiles to restrict syscall access
- Consider gVisor (Google) for sandboxed containers with a user-space kernel
Containers + VMs (The Common Setup)
In practice, containers run inside VMs:
- AWS EC2 instances (VMs) running Docker or Kubernetes
- Kubernetes nodes are VMs; pods are containers on those VMs
You get VM-level isolation at the node level, and container efficiency for packing many workloads per node.
Interview Angle
The key insight: containers share the host kernel (lightweight, less isolated); VMs have their own kernel (heavier, more isolated). Then demonstrate practical knowledge: when you'd use containers (most modern workloads), when VMs are still necessary (strong security isolation, legacy), and how they're used together in Kubernetes.