How does Docker differ from a virtual machine?

6 minintermediatevirtual-machinescontainerscomparison

Quick Answer

A virtual machine virtualizes hardware and runs a complete, separate guest operating system (its own kernel) on top of a hypervisor — heavyweight, but with a very strong isolation boundary. A Docker container shares the host machine's single kernel, using Linux namespaces and cgroups (see that question) to isolate processes from each other — much lighter-weight (starts in milliseconds, far less overhead per instance) but with a comparatively weaker isolation boundary, since a kernel-level vulnerability can, in principle, be exploited across containers sharing that kernel in a way it can't across separate VMs.

Detailed Answer

The architectural difference

Virtual Machines                          Containers
┌─────────┐ ┌─────────┐                  ┌─────────┐ ┌─────────┐
│  App A   │ │  App B   │                  │  App A   │ │  App B   │
│ Bins/Libs│ │ Bins/Libs│                  │ Bins/Libs│ │ Bins/Libs│
│ Guest OS │ │ Guest OS │                  └─────────┘ └─────────┘
│ (own     │ │ (own     │                  ┌───────────────────────┐
│  kernel) │ │  kernel) │                  │   Docker Engine         │
└─────────┘ └─────────┘                  ├───────────────────────┤
┌───────────────────────┐                  │   Host OS (ONE kernel,  │
│      Hypervisor          │                  │   shared by all         │
├───────────────────────┤                  │   containers)            │
│      Host OS               │                  └───────────────────────┘
└───────────────────────┘

Virtual machines: virtualize hardware, run a full guest OS each

Each VM includes its own complete guest operating system with its own kernel, running atop a hypervisor (which itself virtualizes CPU, memory, disk, and network for each guest). This gives very strong isolation: a compromise inside one VM's guest kernel doesn't directly threaten another VM's kernel. But this comes at a real cost. Each VM's guest OS consumes its own chunk of memory and disk just to boot and run, and starting a VM typically takes tens of seconds to minutes (booting an entire operating system).

Containers: share the host's kernel, isolate at the process level

A container is, at its core, just a regular process on the host — isolated from other processes using Linux kernel features (namespaces for what it can see, cgroups for what resources it can use — see that question) rather than running its own separate kernel at all. This means containers start in milliseconds. There's no OS to boot: the kernel is already running, and a container is just a newly isolated process within it. Containers also have far lower memory/disk overhead per instance, since there's no duplicated guest-OS footprint for every single container.

The isolation tradeoff, stated plainly

Virtual MachinesContainers
Isolation boundarySeparate kernel per VM — very strongShared host kernel — weaker, process-level isolation
Startup timeSeconds to minutes (booting an OS)Milliseconds (starting a process)
Resource overhead per instanceHigh (a full guest OS each)Low (just the process and its isolated view)
Density (instances per host)LowerMuch higher
Kernel vulnerabilitiesIsolated to that VM's own kernelCan, in principle, be exploited to escape container isolation and affect the shared host kernel/other containers

Why this tradeoff matters in practice

Containers are the better fit when you need to run many instances of many different applications efficiently, with fast startup, and where the isolation the shared-kernel model provides is sufficient for your trust boundary (see the multi-tenancy discussion in the Kubernetes stack for when it isn't). VMs remain the right choice when you genuinely need the strongest possible isolation between workloads (e.g., running truly untrusted, mutually adversarial code, or needing entirely different kernels/operating systems side by side on the same hardware). The extra overhead is the price paid for a meaningfully stronger security boundary.

They aren't mutually exclusive

In practice, most container workloads run inside VMs anyway. A cloud provider's "bare metal" host running Docker is unusual. More commonly, Docker runs inside a cloud VM instance, which itself runs on a hypervisor shared with other tenants' VMs. This layered approach combines the VM's strong isolation between different customers/tenants at the infrastructure level with the container's lightweight, fast-starting isolation for individual applications within one tenant's own workloads.