Docker containers have become an important tool in the developer’s toolbox. Adoption of this technology has been phenomenal. To date, Docker has surpassed 2 billion container downloads, which increased at a tremendous rate from the reported 300 million downloads in April, 2015. While some organizations have just started to dabble with the technology, others dived in head-first, and they now have burgeoning deployments.
Containers let you construct complex applications from a number of smaller building-block containers, each performing a distinct function. This type of architecture, also known as microservices, is well-suited for building continuously deployed systems, where a microservice component can be updated in place with the other components in the system remaining intact.
But this surge in growth has many enterprise security professionals worried. Dan Walsh of Red Hat has written some excellent articles that explain why containers do not contain. Even though containers offer isolation of system resources, such as memory and CPU cycles, containers running on the same host share the same operating system. Threats targeting one container can conceivably leverage the shared kernel to impact or move laterally into other containers.
While these are legitimate concerns, they are manageable. Let’s look at how the inherent architecture of Docker containers can be leveraged to secure containerized applications.
Docker – the Ability to Isolate Statefulness
Docker containers are built from static images, which are composed of different layers. A layer can be reused in various images. For instance, an Ubuntu base layer may occur in an NGINX container, and it may also occur in a Mongo DB container.
Once an image is instantiated, it becomes a container. In a Docker container, the layers are stacked to present a single, unified view of the container file system. Each layer is instantiated as read-only, and a separate read-write layer is created on top to hold state changes made to the container file system during runtime.
When a container exits and if the user does not explicitly execute “docker –commit,” the read-write layer disappears. No state change is retained, and the image remains the same. If the user does execute “docker –commit,” the read-write layer is permanently added to the previous image and a new image is created. With this method, each “docker –commit” records successive changes, and the container state advances in a controlled, incremental fashion. Not only can you easily roll back to a previous state, it’s also great for traceability, manageability and forensics.
The method of explicitly restricting state changes to the read-write layer is a fundamental shift for security. First, this ensures that most of the code base runs in a read-only state, which means any “badness” during execution will not endure if you do not explicitly commit the changes. Second, it gives you an opportunity to concentrate monitoring to the writable layer.
But, the most important thing is that if a container is stateless, one can more accurately derive a baseline behavior model for it. And, if the observed run-time behavior deviates from the baseline, you know it could be a potential compromise.
This tackles one of the largest problems in threat and anomaly detection, which is developing a usable baseline for what is “normal.” Once you have such a baseline, and can accurately detect anomalies, you can make containers actually “contain” and defend against potential attacks.
Putting Containers to Use
Docker containers give you the ability to run most of your applications as read-only and isolate statefulness to a designated and manageable component. This represents an opportunity for security innovation, but it requires you to truly embrace and leverage the inherent properties of the container architecture.
A digital media company did just that. This company runs numerous services from the cloud for both consumer and business users. The development teams started using Docker and after a year ago the company now runs a significant portion of their services on Docker.
The security team conducted an audit of the entire inventory of container images and they were able to get rid of images that were poorly constructed or those that violated company policies. Next, they instituted a policy where containers will be run as “read-only.” Only special-case applications were allowed to commit runtime changes and, when that happens, the application is carefully logged and traced.
The company is in the middle of the journey to transform most of its applications to microservices and containers. The experience thus far has the security team convinced that—in addition to the fact that they are moving to a more efficient application architecture—the new architecture allows them to prepare for a future where changes are more incremental, more controlled and compromises are more easily detected, contained and managed.