Docker is not a Virtual Machine

| ⌛ 3 minutes read

📋 Tags: Docker Linux Explainer


Docker is not a VM. Neither is it a lightweight VM. But what’s the difference? My dockerfile needs an image of an OS (e.g. Ubuntu) to run, and virtual machines (such as VirtualBox) requires an image of an OS to also run, and both produce similar runtime environments for me to run the code in. Don’t they do the same thing?

The difference is what resources they virtualize.

Hypervisors & Virtual Machines in 30s

Hypervisors (Virtual Machine Managers) emulate hardware resources. They create virtual copies of the underlying machine (hence virtual machines 😉) They allow multiple operating systems to be run at the same time, isolated from one another.

Guest operating systems running on top of a hypervisor get the illusion that the hardware resources (disk, cpu) belongs to them completely, but the hypervisor works as an invisible middleman to the hardware, intercepting requests for hardware resources from different guest operating systems and serving them.

Docker & userlands in 30s

Docker containers emulate userspace environments. They allow multiple userland processes to be run at the same time, isolated from one another with their own userland environements. All of these processes share the host operating system i.e. host kernel.

The userland environment (container) includes a minimal filesystem /, /etc, /bin, /lib with userland tools e.g. /bin/bash. Dependencies that are installed on the environment such as RUN apt-get install -y openssl are installed specific to that environment1. Less dependency hell2 for the developer!

Docker is able to isolate these environments through Linux kernel features such as namespaces. The Docker daemon manages the lifetime of running userland environments, but does nothing to manage how the processes in the environment talk to the host kernel.

Similarities, Differences, Confusion

The reason why Docker and VM gets confused is because both technologies emulate something that gives the effect of a common runtime environment, with isolation of these environments. The difference lies in what the runtime environment is.

VMs provide isolated environments for Operating Systems and manages hardware resource access. Docker provides isolated environments for userland environments and manages the environment lifecycle.

VMs do alot more than containers, which is why containers are much faster than VMs. But containers will not solve all compatability issues…

A note on syscalls, compatability and the need for VMs

Docker doesn’t actually provide full cross-os compatability. It may seem possible at first, since Docker can be run on Windows OS to run an Ubuntu container. But this is a misconception!

To reiterate, Docker containers still interact with the host kernel. When a container does syscalls like open() or write(), it actually calls those syscalls to talk to the host kernel.

Windows has very different kernel API compared to Linux. open() in Linux != open() in Windows. Things will crash and burn.

The reason why Docker on Windows works is because of WSL. It acts like a ‘lightweight vm’ to actually run the linux kernel. For containers running on the WSL ‘Linux VM’ on Windows, Linux syscalls like open() actually exist since the Linux kernel is the underlying OS in the POV of the container. The Linux Kernel here is a ‘guest OS’ and does the whole shebang to actually access hardware resources.

Matrix-level shit, man…

So, perhaps VMs are not slow bloated useless things compared to containers.


  1. This is sometimes Docker image sizes can be really big. ↩︎

  2. What do you mean some_lib v1.0 is incompatible with other_lib v1.1?! ↩︎