As Docker grows in popularity, so does news of Docker security issues. Earlier this year, for instance, the Doki backdoor was used to exploit misconfigured Docker API ports and install cryptominers or other malware. Initially described as undetectable, today only 36/61 scanners on VirusTotal properly flag Doki as malware. Doki is just one example of many potential threats. Last year, CVE-2019-5736 exposed a container security flaw that enabled attackers to gain root access on a host.
Of course, none of this news means Docker is unsuitable for production use. Rather, it provides us of examples of why it’s important to take Docker security seriously. Because Docker images are the starting point for those of you just getting familiar with Docker, they’re also a great place to begin learning about Docker security. Here, we’ll review 6 Docker image security tips to help you keep your projects secure.
1. Apply updates and patches
This one is simple, but we can’t overstate the importance: you MUST keep your Docker images, Docker engine, and hosts patched and up to date. Invariably, there will be new vulnerabilities and patches released to address those vulnerabilities. Get in the habit of applying them regularly. If you’re not applying critical security patches once they are released, the rest of the tips here will quickly become moot points.
2. Only use verified Docker images
One of the major benefits of Docker Hub – Docker’s official Docker registry – is the wealth of available images available for download. Individuals and organizations from around the globe upload images to Docker Hub that you can use. It is true that Docker’s recent changes which throttle free-tier usage can slow things down and hamper serious development. However, there are no-cost solutions — like using JFrog Artifactory’s free tier as a caching proxy – that allow you to get the upside of Docker Hub without overly restrictive rate-limiting. Regardless of the method you use to pull images, how do you know which images you can trust?
That’s where the concept of Docker Content Trust (DCT) comes in. With DCT, image publishers digitally sign images so you can verify the images come from a trusted source. At a high-level, these digital signatures are comparable to SSL certificates for websites. Like websites with SSL certs, verified images aren’t necessarily secure. A bad actor could sign an image or issue an SSL cert. The digital signatures simply let you know that the content is coming from the source you expect. That’s why it’s important to only pull images from sources you trust.
By default, Docker Content Trust is disabled. You can enable it with the command export DOCKER_CONTENT_TRUST=1.
johnnyo@LAPTOP-5V55HON5:~$ export DOCKER_CONTENT_TRUST=1
With that environment variable set, let’s see what happens if we try to pull an unsigned image:
johnnyo@LAPTOP-5V55HON5:~$ docker pull riyaz/unsigned-img
Using default tag: latest
Error: remote trust data does not exist for docker.io/riyaz/unsigned-img: notary.docker.io does not have trust data for docker.io/riyaz/unsigned-img
Note: If you “sudo” your Docker pull commands, be sure to use the -E option to ensure the environment variables you set are used, e.g. sudo -E docker pull your_image_name.
3. Use minimal Docker images whenever possible
As Norwegian researchers demonstrated in a June 2020 “Vulnerability Analysis of 2500 Docker Hub Images” study, there are plenty of vulnerabilities in images on Docker Hub. Even verified images were found to have at least 1 high-rated vulnerability over 50% of the time.
In part, this can be attributed to the fact that many containers have more bloat than they need to provide their core functionality. While it is nice to have all the features a user may ever need crammed into a single image, doing so can greatly increases the attack surface.
Using minimal images — like the official Ubuntu image – and only installing what you need on top of that can mitigate a significant amount of risk.
4. Follow the principle of least privilege
The principle of least privilege is one of the golden rules of information security. The idea is simple: only give users and processes the privileges they need to fulfill the specific tasks required. How can you apply this to Docker security? Here are some of the most common ways:
Run images with the –-security-opt=no-new-privileges option to prevent privilege escalations
Avoid the —privileged flag when running Docker containers. The —privileged flag grants the running container more access to the underlying host’s resources, which means if a privileged container is compromised the entire system could soon be next.
Use —cap-drop and —cap-add to fine-tune the Linux capabilities granted to containers. Ideally, you should use the –cap-drop=ALL option to drop all capabilities by default and then only explicitly add what is needed back with –cap-add.
Follow Docker’s recommendations for isolating containers with a user namespace. Configure your container applications to run as an unprivileged user. In the event an application MUST run as root, map the user to an unprivileged user on the host machine.
Run your Docker containers as a non-root user. One of the easiest ways to do this is to add the non-root user to the Dockerfile for your container.
5. Scan your Docker images for vulnerabilities
Vulnerability scanning is a vital part of information security, and Docker security is no different. Of course, scanning and verifying the security posture of your production deliverables is important. However, to ensure security is baked-in to your CI/CD pipelines, adopting a “shift left” approach to DevSecOps is vital.
How can you do that? By scanning all your containers, software artifacts, and dependencies for existing vulnerabilities. Our own JFrog Xray was built with this “shift left” approach in mind. Xray continuously audits all artifacts, including Docker images, for known vulnerabilities and license issues. Additionally, it is the only Software Composition Analysis (SCA) solution capable of native integration with Artifactory and our Docker registry. By auditing and analyzing your entire CI/CD pipeline with Xray, you can catch vulnerabilities faster and reduce your likelihood of deploying a vulnerable Docker image to production.
6. Harden your Docker hosts
Defense-in-depth is another golden rule of infosec. You can apply this concept to Docker security by ensuring your Docker hosts are hardened. In addition to using SSH keys, strong passwords, and firewalls, solutions that help secure system calls are important here. Linux modules like Selinux, AppArmor, and Seccomp can add a strong layer of defense in the event a given container on a system is compromised.
Final thoughts: Next steps with Docker security
The 6 tips we’ve covered here are a great foundation to help you get started with using Docker securely. Keep these tips in mind as you build out your next project, and you can improve your overall security posture. After putting them into practice at the Docker image level, you can dive deeper into automating your DevSecOps efforts by scaling them with Kubernetes — and we’ve got you covered when that time comes too.