Container security is a important consideration when decidingto use Docker for your applications. Although it is not possible to exhaustively cover Docker security in one post, in this tutorial we will look at how you can make sure applications deployed with docker are secure. Generally Docker containers are less secure compared to virtual machines. These security vulnerabilities are the trade-off for improved performance of containers. All containers on a host share the operating system kernel which is the source of improved performance and reduced security.
This arises because namespacing is not enforced on all the processes running on the kernel. From a security point of view containerized applications are more secure as compared to applications that directly run on the host when you enable cgroups, as well as namespacing also improves security. Containers are not a security solution, therefore as a developer you need to think about how you will secure your applications. It is important to think about privileges that will be allocated to applications that run within your container.
As a developer the first security vulnerability you need to be concerned about is that the operating system root user also happens to be the container root user. Although namespacing tries to remedy this problem by isolating container root from critical filesystem resources, access to resources outside of the namespace will still be treated as root. The default Docker behavior is to start all container processes as root therefore privilege management is the responsibility of the developer.
Having privileged containers is not a bad thing because some situations require them for your applications to run properly. For example if you have applications that need to change network configurations, non privileged containers will not be useful in such situations. Normally the kernel blocks non privileged containers from performing privileged operations. A privileged container is created by passing the –privileged = true flag when launching it. When we pass the –privileged flag, we give a very broad set of privileges to the container. In practice, usually fewer privileges are needed than those granted. This may become a security vulnerability. To remedy this it is important to identify the specific privileges that are required by your container then you can specify them when launching your container. For example if our container only needs to change MAC address we can use the command below to grant only that privilege.
docker run -ti --rm --cap-add=NET_ADMIN ubuntu /bin/bash
In the above command, we are launching our container using the run command and adding the desired privileges. To add or remove privileges we use –cap-add and –cap-drop options on the run command.
Privileges is one of the ways we can enforce security in Docker containers. Two other options available for enforcing security are Apparmor and Selinux. These two systems help you enforce security controls on top of those available on Unix. AppArmor comes pre-installed on ubuntu while is available for download on CentOS/RHEL/Fedora SELinux . These systems help you enforce security by implementing mandatory access controls (MAC). When MAC is implemented all resources are given security labels. Security labels have the classification and category of the resource. For example, a resource could be classified as top secret and categorized into an appropriate management level. When users need to access resources, MAC checks the classification and category assigned to the user against those of the resource. When both, the classification and category of the user and those of the resource match access is granted, otherwise it is denied.
MAC gives very fine control to resource access but it requires detailed planning.
The Docker demon faces challenges of other applications that run over the network. Specifically Docker faces vulnerabilities posed by race conditions and buffer overflows. The first option to secure your Docker daemon is to use certificates to make sure traffic between all your servers is encrypted. This is well explained in the Docker documentation and the reader is referred there. The second option is to implement some form of authorization. Docker does not provide any form of authorization but it provides authentication through signed certificates. The Docker documentation also provides information on how to use certificates. Exposing docker to the internet is not recommended instead you should use VPN or SSH.
Another way of enforcing security in Docker is ensuring images that are downloaded from repositories are of good integrity. This is possible by enforcing content trust. With content trust you are able to use digital signatures for client side verification of image integrity. By default content trust is not enabled so you need to enable it by modifying the DOCKER_CONTENT_TRUST variable. The Docker documentation explains how this is done. When content trust is enabled you can only you can only pull and build images that have been signed.
In this tutorial, we introduced the importance of security in Docker. We noted that containers are less secure as compared to virtual machines. We discussed how to set privileges when running containers to ensure they are only able to do what is required. We also identified mandatory access control as another way of securing your Docker containers. Finally we discussed content trust as a way of ensuring the integrity of images that we download and use to build containers.