Containers vs virtual machines
Containers were not the first fix for the environment problem. Virtual machines (VMs) came first.
A VM is a complete simulated computer. A piece of software called a hypervisor carves your physical machine into fake machines, and each VM boots its own full guest operating system: its own kernel, its own system services, everything. Great isolation, but heavy. A VM image is often gigabytes and takes minutes to boot.
A container skips the guest OS. All containers on a machine share the host's kernel (the OS core that talks to hardware). Docker uses Linux kernel features called namespaces to isolate only what each container can see: its own filesystem, its own processes, its own network. So a container is just a normal process wearing a blindfold, which is why it starts in milliseconds.
Honest comparison
| VM | Container | |
|---|---|---|
| Starts in | minutes | milliseconds |
| Typical size | gigabytes | megabytes |
| Runs its own kernel | yes | no, shares host |
| Isolation strength | stronger (hardware-level) | good, but weaker |
| Per-machine density | a handful | hundreds |
Note the isolation row. VMs still win when you must run untrusted code or a different OS entirely, which is why cloud providers run your containers inside their VMs. For packaging and shipping your own apps, containers are the right default.
You will see this hybrid again in lesson 9-1 when we compare deployment options.
Why a container starts in milliseconds
A container starts in milliseconds because it skips booting a guest OS, sharing the host's kernel instead.
Starting a container is essentially starting a normal process with an isolated view of the system. Starting a VM means booting an entire operating system, kernel and all, on simulated hardware.
| Startup work | Container | Virtual machine |
|---|---|---|
| boot a kernel | no | yes |
| start init and system services | no | yes |
| launch the application process | yes | yes |
No guest OS boot is the whole speed story. It is also the whole size story, since a container image carries an application and its libraries while a VM image carries an operating system too.
Running untrusted code from strangers
For completely untrusted code submitted by strangers, the right choice is a VM, because a separate guest kernel per tenant is stronger isolation than sharing the host kernel.
All containers share the host kernel, so a kernel exploit in one container threatens everything on the machine. A VM gives the untrusted code its own kernel on simulated hardware, which is a much thicker wall.
| Threat | Container | VM |
|---|---|---|
| escaping into another tenant | one kernel bug away | needs a hypervisor bug |
| stealing CPU or memory | limited by cgroups | limited by the hypervisor |
This is exactly why cloud providers run customer containers inside their own VMs, and why online code runners execute submissions in heavily sandboxed VMs rather than bare containers.
Which one shares the host kernel
Containers share the host machine's kernel instead of booting their own.
Every container on a host runs on that host's single kernel, with namespaces hiding everything it should not see. A VM instead runs a complete guest OS with its own kernel on virtual hardware.
| Property | Container | VM |
|---|---|---|
| kernel | shared with the host | its own |
| typical image size | tens of megabytes | gigabytes |
| isolation strength | good | stronger |
The VM pays size and boot time and buys stronger isolation, which is the entire trade between the two. Neither is a strictly better technology, and production systems routinely use both at once.