VMs vs LXC vs Docker
When should I use a VM vs LXC vs Docker?
Virtual machines (VMs), Linux containers (LXC), and OCI containers (Docker) are all virtualization technologies that allow us to separate programs from the host system. This provides added security and a certain degree of "oops" protection when running untrusted or experimental code.
For some time, I've struggled to figure out how I should decide which tool is appropriate for which situation. Just the other day I had an epiphany and realized this simple decision process:
The TL;DR is:
- If I need to run a separate CPU architecture or separate OS kernel, I use a VM.
- If I don't care about running a separate kernel but still need a full init system, I use LXC.
- If I just want to run an isolated application, I use OCI containers.
Overview of Each Tool
Virtual Machines
A virtual machine is a full system also called a "guest", that usually includes a bootloader, kernel, initramfs, and root filesystem. They run on virtualization environments (VEs) like qemu, xen, and virtualbox. The VE or host provides the guest kernel with virtual hardware, i.e. code that acts like hardware and provides a host-controlled bridge between the real hardware and guest. This makes the guest VMs highly isolated from the host, and the guest can even run kernels that are compiled for different architectures than the hostfor example a RISCV guest running on an x86_64 host.
PROS
VMs are the most flexible option, as the host VE has complete programmatic control over the virtual hardware the guest has access to. VMs can also be easily "broken out" into a bare-metal machine by writing their backing storage to a physical storage device and putting it in a separate machine.
CONS
VMs require an entirely separate kernel and thus take up a lot of memory. Because their hardware is fully virtualized, there is also additional computational overhead needed to manage access to the virtual hardware.
LXC
LXC is the name given to a bundle of userspace tools that leverage
Linux kernel containment features like
chroot(1)
and
cgroups(7)
to create environments that are separate from the host but without
requiring full hardware virtualization like VMs. If VMs virtualize
hardware resources, LXC containers virtualize kernel resources.
LXC containers are primarily intended to run a full OS (minus the
kernel), so they usually include an init system like
systemd(1)
or
openrc
. This makes them an excellent drop-in replacement for VMs when
kernel separation is not a requirement.
PROS
Full OS virtualization without needing to run a separate kernel.
CONS
Less flexibility than VMs due to reliance on the same kernel and slower startup than OCI containers due to the init system startup time.
OCI Containers (Docker)
OCI containersformerly known as Docker containersrely on the same Linux kernel containment features as LXC, but were built with a different use-case in mind: microservices.
Each OCI container usually only runs a single process and therefore does not need any sort of init system. Additionally each container is meant to be run from a stateless base filesystem for increased reproducibility, so if a containerized application malfunctions then restarting the container will run it from a fresh state.
PROS
Fast startup and reproducibility.
CONS
Only intended to run a single microservice-oriented application.
Summary
Any of the tools mentioned above can be used to run any application. The question about which tool to use comes down to resource consumption and efficiency.
VMs are resource-intensive but provide the greatest flexibility.
LXC containers are less resource-intensive but are still meant to run full systems.
OCI containers are the least resource-intensive but require the adoption of a microservice-oriented application deployment strategy.