No, Docker containers are not more secure than a VM.
Quoting Daniel Shapira:
In 2017 alone, 434 linux kernel exploits were found, and as you have seen in this post, kernel exploits can be devastating for containerized environments. This is because containers share the same kernel as the host, thus trusting the built-in protection mechanisms alone isn’t sufficient.
1. Kernel exploits from a container
If someone exploits a kernel bug inside a container, they exploited it on the host OS. If this exploit allows for code execution, it will be executed on the host OS, not inside the container.
If this exploit allows for arbitrary memory access, the attacker can change or read any data for any other container.
On a VM, the process is longer: the attacker would have to exploit both the VM kernel, the hypervisor, and the host kernel (and this may not be the same as the VM kernel).
2. Resource starvation
As all the containers share the same kernel and the same resources, if the access to some resource is not constrained, one container can use it all up and starve the host OS and the other containers.
On a VM, the resources are defined by the hypervisor, so no VM can deny the host OS from any resource, as the hypervisor itself can be configured to make restricted use of resources.
3. Container breakout
If any user inside a container is able to escape the container using some exploit or misconfiguration, they will have access to all containers running on the host. That happens because the same user running the docker engine is the user running the containers. If any exploit executes code on the host, it will execute under the privileges of the docker engine, so it can access any container.
4. Data separation
On a docker container, there’re some resources that are not namespaced:
- file systems under
- Kernel Modules
If any attacker can exploit any of those elements, they will own the host OS.
A VM OS will not have direct access to any of those elements. It will talk to the hypervisor, and the hypervisor will make the appropriate system calls to the host OS. It will filter out invalid calls, adding a layer of security.
5. Raw Sockets
The default Docker Unix socket (
/var/run/docker.sock) can be mounted by any container if not properly secured. If some container mounts this socket, it can shutdown, start or create new images.
If it’s properly configured and secured, you can achieve a high level of security with a docker container, but it will be less than a properly configured VM. No matter how much hardening tools are employed, a VM will always be more secure. Bare metal isolation is even more secure than a VM. Some bare metal implementations (IBM PR/SM for example) can guarantee that the partitions are as separated as if they were on separate hardware. As far as I know, there’s no way to escape a PR/SM virtualization.
Saying either a VM or Docker is more secure than the other is a massive over simplification.
VM provides hardware virtualization; the hypervisor emulates hardware so that the guest kernel thinks it is running on its own machine. This type of virtualization is easier to isolate from one another. If your primary concern for virtualization is isolation (you don’t really need the virtual machines to interact with each other), then VM is going to be significantly simpler to secure.
Docker provides kernel/operating system virtualization, and Docker uses the kernel namespaces to virtualize the kernel and the operating system so that the guest thinks it is running on its own instance of the operating system. Operating system virtualization provides significantly more flexibility on how you can secure the interconnection between your containers. If your primary concern for virtualization requires you to interconnect containers, then Docker provides the ability to define these sharing rules in ways that are impossible or too cumbersome with virtual machines.
With great flexibility comes great risks; it’s easier to misconfigure docker than VM, and the flexibility of docker resource sharing also creates more opportunities for both implementation and configuration bugs. However, if you manage to configure the sharing permissions properly and assuming there are no implementation bugs in Docker or the kernel, then Docker provides much more fine-grained sharing than hardware virtualization and may give you overall better security.
For example, socket sharing. With Docker, you can create a shared named socket between two containers easily by sharing the socket file, and you can define security permissions (using any existing security modules: traditional Unix permission, capabilities, SELinux, AppArmor, seccomp, etc.) between the socket endpoints so that the docker/kernel enforces which and how applications can access the socket endpoints. With a virtual machine, you can share a socket a bit more cumbersome by setting up a chain of sockets to pipe data going to the socket via TCP. However, the hypervisor has very limited visibility and no way to control access to the socket endpoints, because permissions to these socket end points are applied by the guest kernels.
Another example is folder sharing. With containers, you can share a folder by setting up a shared mount, and since the Docker/kernel enforces file permissions that is used by containers, the guest system can’t bypass that restrictions. With a VM, if you want to share folder you have to let one machine run a network file server or Samba server or FTP server, and the hypervisor have little visibility into the share and can’t enforce sharing permissions. The additional moving parts here (the file server), may also have its own vulnerabilities and misconfiguration issues to consider.
TL;DR: Use VM for isolation and containers for controlled sharing.
As you correctly stated, Docker uses “Operating-system-level virtualization”. You can think of this (if you are a *nix fan) as a fancy form of
By harnessing features and functionality built into the OS, Docker acts as a director for containers. The software’s view of the OS is dictated by Docker.
The same kernel is used across all containers. So for instance, if I was able to cause a kernel panic in one container (think “Blue Screen of Death”), all other containers are affected.
Configuration seems to be much more critical than with hardware based solutions. Everything is in the same shared space effectively. Imagine putting a wild predator beside it’s natural food source. If you didn’t put a strong enough enclosure surrounding the predator, or forgot to shut the gate every time you left it’s enclosure, you can likely imagine what would happen.
While certainly a lightweight solution, I certainly wouldn’t run any unknown code along side that of trusted code.
Malicious code would have to determine a way to escalate it’s privileges to a root/Administrator level in order to escape the container in any meaningful way.
In a virtual machine, the hypervisor would be attacked, not the kernel. This may prove more secure as there is a higher level of isolation between “containers” but introduces higher overhead for management.
From my understanding, there’s nothing that makes Docker more secure than “bare metal” or hardware based solutions. I would be inclined to say that Docker is less secure. In terms of 1 container per a piece of software, that can prove a different story.
If you are unsure of real world examples, I would take a look at OpenVZ. It uses OS level virtualization in a similar style just as Docker does, but with a modified kernel.