Containers have become an irreplaceable part of cloud environments. They present numerous advantages for developers such as flexibility and control over the deployment of their applications and microservice. Of course, as is the case with all technologies, containers have introduced their own unique challenges and threats from a security perspective.
What is container security?
Why is container security important?
Docker popularized and simplified the use of container technologies and made it simple for developers all over the world to publish their container images on Docker Hub. In the past several years, the use of containers has exploded and the number of container images that are publicly available has grown exponentially.
On Docker Hub there are over 6 million repositories, from which over 8 Billion images were pulled in the last month alone! As more organizations shift to a container-first development and operations model, these numbers will continue to grow, making container security an even bigger concern.
Selecting a good starting point to build upon can be a challenge. The nature of containers makes it easy to take any existing container and add your software and tools to create a new, unique image.
Unfortunately, with all of these publicly available images, there are many produced by bad actors. Crypto-miners, backdoors, and outdated, insecure software packages are common. According to the latest State of Open Source Research – even the official images curated and maintained by Docker can have operating system vulnerabilities.
Four steps to creating secure container images
1. Secure your code and its dependencies
Your code is the whole reason containers exist and is the lifeblood of your organization. No matter what you do with the rest of the container, if your code isn’t secure, it doesn’t matter. Fortunately, this is the portion of the container that’s most directly controlled by developers and (usually) the best understood.
Snyk Open Source helps you automatically detect open source vulnerabilities and accelerate fixing throughout your development process. Snyk makes fixing your code simple with Fix PRs powered by our proprietary security database for the most popular open-source languages and frameworks.
2. Start with a minimal base image from a trusted source
The base image – the FROM line in your Dockerfile – is one of the most important considerations when it comes to container security. Fortunately, some trustworthy vendors provide content you can easily use.
Docker, Red Hat, Microsoft, many Linux vendors and VMware / Bitnami are providing some level of certified container images. These cover almost every programming language and framework in widespread use today. Of course, you can elect to choose base images with just the operating system and package manager and customize the language support on your own as well. Almost all of these providers sign their images with tools like Notary so you can verify their source and authenticity.
With selecting images from trusted sources and verifying the digital signatures on the images, you should consider selecting images with minimal operating system footprints as well:
- On Docker Hub you’ll find images that use Alpine, which is a small Linux distribution well suited to containers
- You can also find images tagged ‘slim’ which generally remove tools like compilers which shouldn’t be needed in production
- The Ubuntu images on Docker Hub are trimmed down versions of that distribution
- Red Hat provides their own ‘minimal’ and ‘platform’ UBI images that strip things down to the basics.
3. Manage all the layers in between the base image and your code
You – or your developers, DevOps teams, and application security folks – control the middle layers. Everything between the first FROM line and the final Dockerfile lines where you set up your code to run. Once you’ve identified your preferred base image you can then add the tools you need to develop, test, and deploy your applications. At each stage of the software lifecycle, you might need different sets of tools, and in production, you likely want to remove everything that isn’t absolutely necessary.
Customizing your images by starting with a minimal base and then adding your tools makes it very easy to remove these tools later by simply taking them out of the Dockerfile and rebuilding, or even better, by using multi-stage builds with different build targets.
4. Manage your runtime configuration
Finally, for the container image there are configuration details that will further help secure the container as it runs, and limit damage in case an application is ever breached. Within the Dockerfile you can set up your image so that it runs as a non-root user with the USER instruction.
When you run containers, particularly with an orchestrator like Kubernetes, you can enforce policies regarding non-root users, and also set additional controls that drop Linux system capabilities, limit CPU and memory utilization, limit the ability to mount external storage, and more
How to secure your container build pipelines and CI/CD
A good place to make vulnerability scanning part of your standard quality and security process is your CI pipelines. The idea is to scan containers as they’re built in the pipeline and then act based on the results.
What many organizations do as their container usage grows is to have image repositories that correspond to various stages of the pipeline: repositories accessible to developers have less stringent controls but after that images must be pushed only by automation tools after all checks have passed. This sets up security gates that ensure that images that reach production must follow your testing and deployment processes, reinforcing container security as a whole.
Monitoring containers at runtime
When your containers are deployed and running, you can’t assume they’ll remain safe. New vulnerabilities get reported daily, misconfigurations can permit attacks even if your code and containers are secure, and sometimes users manage to find a way to deploy workloads that go around security and quality gates.
When it comes to container security, you should monitor the clusters where your workloads run so that you are aware and alerted to any new vulnerabilities that affect the code and container. You can then go back to the source, make the changes needed to eliminate new vulnerabilities, and update your deployments.
The configuration of your deployments should also be checked, preferably in a manner that ties back to the code used to create the deployment so that if there are issues they can be addressed at the source.