Docker – The Difference Between Containers and Virtual Machines (VMs)

Docker is all the rage now in technology circles and there is a great deal of misperception around the technology. In particular, I have heard a lot lately the Docker is the “next wave of virtualization.” This has started to sprout the factually inaccurate belief that Docker containers are like VMs. In turns out, this is fundamentally untrue and there are some very explicit differences that matter.


Containers are dramatically more efficient that VMs. They can be created and disposed of almost instantaneously as opposed to VMs that are much heavier. A Docker wrapper can be as small as 12 KB while VMs are typically in the GB(s) range just for the guest Operating System (OS). In addition, Docker containers have a shared underlying host OS which means they can be packed on bare metal much more densely than VMs. These efficiency improvements in spin up and density are what is prompting people to say containers will make virtualization obsolete. However, they are missing a very important point (see next section).


Containers do not have anywhere near the isolation provided by VMs. A Type 1 hypervisor like VMware provides a high degree of isolation by having each VM run a separate operating system with resources (CPU, Memory, and Disk) dedicated to the VM. Containers run a shared OS…meaning that all containers run on top of one base Linux image. This is absolutely great for efficiency as each container is basically just an isolated running process on the Linux box. However, it is awful for security isolation as each container shares memory with the other containers on the box creating avenues for exploitation and lateral movement. In my mind, this problem is currently the single greatest barrier to Docker adoption as it creates a significant security risk that does not really exist on a hypervisor.

Layered Filesystem

Containers are also different in the sense that they are layered versus the traditional monolithic VM. This approach makes it easy to tweak an existing container and efficiently rebuild since it only changes the affected layers and not the total image. This approach is great for extensibility and saves time on deployment since you only have to ship the changed layers. Conversely, VMs are very heavy in nature and require updating the entire VM image. This makes it difficult to quickly/agilely update releases on a VM and they are more bandwidth intensive to move.


Another big difference is that containers work best when they do not need to maintain state. They can be much more ephemeral than VMs and quickly spun up and torn down. With Docker, it is much more desirable to move any configuration data into Environmental Variables rather than have them in the image or to maintain state. This approach has a lot of upsides but it often requires applications to be de-composed into micro-services and the bare essentials for each service to take full advantage of Docker. This can be great for agile and maintainable new Linux development projects. However, VMs will still be necessary for legacy code or any code base where you need to make heavy use of maintaining state. In these cases, a long running VM is still often the best choice.


While containers will be hugely disruptive in the coming years and will dramatically change application development for the better, they are not the same as VMs, are unlikely to replace VMs in the foreseeable future, and still have significant pros/cons when comparing use cases. Docker has matured into a state where it is ready for primetime and suitable for production use. However, VMs have a lot more maturity in their feature sets, tooling, and eco-system that it will take Docker years to match. Now is a great time to hop on the band wagon, start learning the innovative technology, and find some good low-hanging-fruit use cases….just don’t go crazy and abandon your VM infrastructure just yet.