Posted on 26 Jul 2026
This is the second article of the Getting Started with Docker series. In the previous article we introduced Docker and ran our first container. Before going further, it is worth spending time on a fundamental question: what is the real difference between a container and a virtual machine?
When I started working with Docker this was not easy to grasp. The two technologies look similar from the outside — both give you an isolated environment to run software — but they work in completely different ways under the hood.
Virtualization can be achieved in two ways:
Historically, as server processing power grew, applications running on bare metal couldn’t exploit the abundance of available resources. Virtual Machines were born to solve this: by running a hypervisor on top of physical hardware, you could carve up one server into many independent guest systems.
A hypervisor (also called Virtual Machine Monitor) is the software layer that sits between the hardware and the virtual machines. It can be type 1 (bare metal, like VMware ESXi or KVM) or type 2 (hosted, like VirtualBox or Parallels).
Each VM includes:
The system running the VMs is called the host, the systems running inside are called guests.
The rise of VMs gave birth to the Infrastructure as a Service (IaaS) market. Companies like Amazon, Microsoft, and IBM allow you to rent virtual machines on demand. A startup today does not need to buy physical hardware — it registers an account with a cloud provider, orders a VM with the required specs, and is ready in minutes.
A container is an isolated environment created using features of the Linux kernel itself — not a separate hypervisor. Multiple containers run on the same host, all sharing the same OS kernel, but each seeing its own isolated filesystem, processes, network, and users.
The two kernel mechanisms that make this possible are:
Together, namespaces and cgroups create the illusion of a separate machine without the overhead of emulating hardware or running a second kernel.
Important note for Mac and Windows users: because containers rely on Linux kernel features, Docker and Podman on macOS and Windows run a lightweight Linux VM behind the scenes (using Apple’s Virtualization Framework on Mac, and WSL2 on Windows). Your containers still run in that Linux environment — you just don’t see it.
Mike Coleman on the Docker official blog provides a memorable analogy:
Houses (VMs) are fully self-contained and offer protection from unwanted guests. They each possess their own infrastructure — plumbing, heating, electrical. Apartments (containers) also offer protection from unwanted guests, but they are built around shared infrastructure. The apartment building (Docker Host) shares plumbing, heating, electrical. Apartments are offered in all kinds of sizes — from studio to penthouse. You only rent exactly what you need.
In practice, containers and VMs are often used together, not in opposition. The most common production setup is:
VMs provide the strong isolation boundary at the infrastructure level. Containers provide the lightweight, fast, portable packaging for applications within that boundary.
In this article we covered:
The next article focuses on Dockerfiles: how to write your own image definition and build a custom container image from scratch.
If you enjoyed this article, don’t forget to give it a clap 👏, share it with your friends 🔗, and follow me for more tips and tutorials on software development 📘. Your support helps me create more content like this — thank you! 🙌