A virtual machine runs a complete operating system, with its own kernel, on virtual hardware provided by a hypervisor. A Docker container is an isolated process that shares the host's kernel, so it carries only the application and its files; that makes containers lighter and faster to start, while VMs give stronger isolation and can run a different operating system.
How a virtual machine works
A hypervisor (Hyper-V, VMware, VirtualBox, KVM, Apple's Virtualization framework) gives each VM virtual CPUs, memory, a virtual disk and network adapters. The VM boots a full operating system on that virtual hardware: its own kernel, drivers and system services, exactly as if it were a separate computer. Microsoft's comparison puts it this way: VMs "run a complete operating system, including its own kernel", which means "more system resources (CPU, memory, and storage)".
Because the guest has its own kernel, it can be anything the virtual hardware supports: Linux on a Windows host, Windows on a Mac, an old OS version for testing.
How a Docker container works
Docker's documentation describes a container as "simply an isolated process with all of the files it needs to run", and adds: "If you run multiple containers, they all share the same kernel." There is no second operating system booting. The isolation comes from features of the Linux kernel:
- Namespaces give the container its own view of processes, network interfaces, mount points and host name. Docker's security guide: processes in one container "cannot see, and even less affect, processes running in another container".
- Control groups (cgroups) limit and account for CPU, memory and I/O, so "a single container cannot bring the system down by exhausting one of those resources."
The container's files come from an image, which Docker defines as "a read-only template with instructions for creating a Docker container". An image holds the application, its libraries and a minimal set of user-space tools from a distribution such as Debian or Alpine, but no kernel.
Docker vs VM compared
| Virtual machine | Docker container | |
|---|---|---|
| What runs | A full OS: kernel, drivers, services, then your app | Your app's process(es) on the host kernel |
| Kernel | Its own | Shared with the host |
| Guest OS | Almost any OS the virtual hardware supports | Same kernel type as the host (Linux containers need a Linux kernel) |
| Isolation | Strong boundary at the hypervisor | Kernel features; weaker boundary, one shared kernel |
| Size on disk | Includes a whole OS install | App plus libraries; no kernel or boot files |
| Startup | Boots an operating system | Starts a process |
| Typical tools | Hyper-V, VMware, VirtualBox, KVM, UTM | Docker, Podman, containerd, Kubernetes |
We have left exact sizes and startup times out of the table on purpose. They depend entirely on the image, the OS and the hardware, and published figures are usually best cases. The direction is consistent, though: a container skips the kernel boot and the OS install, so it starts sooner and takes less space than a VM running the same application.
Which is more secure?
A VM. Microsoft's comparison says a VM "provides complete isolation from the host operating system and other VMs", while a container "typically provides lightweight isolation from the host and other containers, but doesn't provide as strong a security boundary as a VM."
The reason is the shared kernel. Every container on a host makes system calls into the same kernel, so a kernel vulnerability can let a process escape its container. A VM's guest kernel is separated from the host by the hypervisor.
Docker adds a second consideration of its own: the Docker daemon "requires root privileges" unless you opt into rootless mode, so "only trusted users should be allowed to control your Docker daemon." Mounting the host's root folder into a container, for example, lets that container "alter your host filesystem without any restriction." Treat membership of the docker group on Linux as equivalent to admin access.
Containers can be hardened. Docker's guide recommends removing all Linux capabilities except those a process needs, and running as a non-root user inside the container helps too. But for code you don't trust, a VM (or a container inside a VM) is the safer default.
Docker on Windows and macOS actually runs a VM
Linux containers need a Linux kernel, and Windows and macOS don't have one. So Docker Desktop quietly runs a small Linux VM and puts the containers inside it:
- Windows: Docker Desktop's WSL 2 backend "runs inside its own
docker-desktopWSL distribution". WSL 2 itself runs a real Linux kernel "inside of a lightweight utility virtual machine", according to Microsoft. On a Windows 11 machine with Docker Desktop installed,wsl -l -vlists it alongside any distributions you installed yourself:
NAME STATE VERSION
* docker-desktop-data Stopped 2
docker-desktop Stopped 2
Ubuntu Stopped 2
- macOS: Docker's documentation says it "supports multiple Virtual Machine Managers (VMMs) to power the Linux VM that runs containers", including Apple's Virtualization framework and Docker's own Docker VMM.
- Linux: Docker Engine runs containers directly on the host kernel, with no VM. Docker Desktop for Linux is the exception: it "runs a Virtual Machine (VM)" and keeps its containers and images separate from a host Docker Engine.
Docker's WSL page also notes that on Windows you can choose the Hyper-V backend instead of WSL 2 "to avoid the shared-kernel model entirely", if keeping Docker's kernel separate from your WSL distributions matters to you. For more on WSL itself, see how to install WSL.
The practical consequences on Windows and Mac: the VM uses memory and disk of its own, and images and containers live inside the VM's virtual disk, which is why Docker's data can grow large. docker system prune removes stopped containers, unused networks, dangling images and unused build cache. File access that crosses the VM boundary is also slower: Microsoft's WSL comparison lists performance across OS file systems as a weak spot of WSL 2, and recommends keeping project files on the same side as the tools that use them.
When to use a container and when to use a VM
Use containers when you want to:
- Package an application with its exact dependencies so it runs the same on a laptop, a CI server and production.
- Run several services side by side (a web app, a database, a cache) without installing each one on your machine.
- Start and throw away environments quickly, for tests or for trying a tool.
- Pack many small services onto the same machines.
Use a VM when you need to:
- Run a different operating system or kernel: Windows on a Mac, a specific Linux kernel version, an old OS.
- Isolate untrusted code, or tenants who must not be able to affect each other.
- Run software that expects a whole machine: kernel modules, its own init system, desktop environments, low-level drivers.
They are not mutually exclusive. Docker's documentation points out that in the cloud "the provisioned machines are typically VMs", and each VM runs a container runtime hosting many containers. That combination gets the VM's isolation between customers and the container's density inside each one.
Common misunderstandings
- "A container includes an operating system." It includes a distribution's user-space files (shell, package manager, libraries) but not a kernel.
uname -rinside a container reports the host's kernel version. - "Containers are tiny VMs." They are processes. On a Linux host, a container's processes show up in the host's
psoutput. - "Data in a container is saved." Changes inside a container are lost when you remove it. Use volumes or bind mounts for anything you need to keep.
If a container's port clashes with something already running on your machine, fixing "port already in use" covers how to find which process holds it.
Frequently asked questions
- Is a Docker container a virtual machine?
- No. A container is an isolated process running on the host's own kernel, with its own view of files, processes and network. A virtual machine emulates hardware and boots a complete operating system with its own kernel. On Windows and macOS, Docker Desktop does run a Linux VM in the background, but the containers inside it are still processes sharing that VM's kernel.
- Can I run a Windows container on Linux, or a Linux container on Windows?
- Not directly, because a container uses the host's kernel. Linux containers need a Linux kernel, which is why Docker Desktop on Windows and macOS runs a Linux VM. Windows containers need a Windows host whose version is compatible with the container image. To run a different operating system outright, use a virtual machine.
- Is Docker more secure than a VM?
- Generally the opposite. Microsoft describes VMs as providing complete isolation from the host and containers as lightweight isolation that does not provide as strong a security boundary. Docker's own security guide adds that the Docker daemon requires root privileges by default, so only trusted users should control it. Containers can be hardened, but a VM is the stronger boundary for untrusted code.
- Do I need Docker Desktop to use Docker?
- On Linux, no: you can install Docker Engine directly and containers run on the host kernel without any VM. On Windows and macOS, you need something that provides a Linux kernel, such as Docker Desktop or Docker Engine installed inside a WSL 2 distribution or another Linux VM.
Sources
- Docker Docs — What is a container?
- Docker Docs — Docker overview
- Docker Docs — Docker Engine security
- Docker Docs — Docker Desktop WSL 2 backend on Windows
- Docker Docs — Virtual Machine Manager for Docker Desktop on Mac
- Docker Docs — Install Docker Desktop on Linux
- Microsoft Learn — Containers vs. virtual machines
- Microsoft Learn — Comparing WSL versions