Docker containers are very similar to LXC containers, and they have similar security features. When you start a container with
docker run, behind the scenes Docker creates a set of namespaces and control groups for the container.
Namespaces provide the first and most straightforward form of isolation: processes running within a container cannot see, and even less affect, processes running in another container, or in the host system.
Each container also gets its own network stack: a container doesn’t get privileged access to the sockets or interfaces of another container. Of course, if the host system is setup accordingly, containers can interact with each other through their respective network interfaces.
Control Groups are another key component of Linux Containers. They implement resource accounting and limiting. They provide many useful metrics, but they also help ensure that each container gets its fair share of memory, CPU, disk I/O; and, more importantly, that a single container cannot bring the system down by exhausting one of those resources.
Docker daemon attack surface
Running containers (and applications) with Docker implies running the Docker daemon. This daemon currently requires
root privileges, and therefore, only trusted users should be allowed to control your Docker daemon.
Linux kernel capabilities
By default, Docker starts containers with a restricted set of capabilities.
Capabilities turn the binary “root/non-root” dichotomy into a fine-grained access control system. Processes (like web servers) that just need to bind on a port below 1024 do not need to run as root: they can just be granted the
net_bind_service capability instead. And there are many other capabilities, for almost all the specific areas where root privileges are usually needed.
Docker containers are, by default, quite secure; especially if you run your processes as non-privileged users inside the container. You can add an extra layer of safety by enabling AppArmor, SELinux, GRSEC, or another appropriate hardening system.