Amir Jerbi, CTO and Co-founder, Aqua Security, outlines the top 20 Docker security best practices.
Docker security has been long associated with containerization and the fundamental requirements for building new secure container-based applications stemming from Docker security are still applied to newer platforms today. This guide will provide the 20 essential Docker/container security practices to help users build their own secure containers.
Docker and host configuration
1. Regularly update host and Docker engine
To reduce weaknesses within a Docker run environment, both the Docker Engine and the underlying host operating system running Docker must be updated regularly.
2. Protect the daemon socket
The Docker client communicates with the Docker daemon through a local UNIX socket – /var/run/docker.sock. It is owned by the root user, but if it is exposed then anyone who accesses it will have permissions equivalent to root access to the host.
Never make the daemon socket available for remote connections. Avoid running Docker images with an option like -v /var/run/docker.sock://var/run/docker.sock, as these expose the socket.
3. Avoid running privileged containers
Running container with “–privileged” flag provides this container all the Kernel capabilities. Privileged containers are a security risk that enable attackers to access to the host.
4. Use rootless mode
Unlike privileged mode, Docker’s “rootless mode” is a benefit. By allowing containers and Docker daemons to be run with non-root users, rootless mode runs daemons and containers without root privileges by default. This helps reduce the vulnerabilities in runtime.
5. Set resource quotas
Threat actors often try to access the underlying host resources of a container once it is compromised. Setting resource quotas limits potential damage by reducing the resources that the container can use. Docker memory and CPU usage limits should also be minimized.
6. Do not rely on the default bridge network
Instead of relying on the default bridge network for new containers it is better to create custom bridge networks that enable a greater level of control over which containers can communicate between them. There is no limit to the number of networks that can be created, and each can be customized to allow specific connections.
7. Improve Container Isolation
Operations teams should create an optimized environment to run containers. Ideally, the operating system on a container host should protect the host kernel from container escapes and prevent mutual influence between containers.
8. Set containers to read-only
A simple security trick is to set filesystem and volumes to read-only. This prevents malicious activity such as manipulating the configuration of the container.
9. Restrict system calls
In a container, you can choose to allow or deny any system calls. Not all system calls are required to run a container.
You can monitor the container, obtain a list of all system calls made, explicitly allow those calls and no others. It is important to base your configuration on observation of the container at runtime because you may not be aware of the specific system calls used by your container’s components, and how those calls are named in the underlying operating system.
10. Full lifecycle maintenance
At every stage of the application lifecycle, it is important to implement security controls and mitigation techniques to improve security. Consider automating patching, and test for vulnerabilities throughout the development’s lifecycle. Creating a sandbox environment to QA code before production can reduce vulnerabilities from appearing in runtime. Lastly, enable full scale forensics tools to fine-tune troubleshooting and ensure rapid remediation in case of an attack.
11. Use minimal base images
When choosing base images ensure that they meet the project’s requirements. If possible, try customizing a unique minimal base image to reduce the attack surface. Extra elements to base images can leave more room for attackers to gain access.
12. Test and verify container images
Docker images need to be tested before use, particularly if they are originally from public sources which can come with risks. Vulnerabilities in a base image will be carried into new images that are created from that base image which are then susceptible to attacks during container runtime.
With numerous open source scanners to choose from, be sure to verify that the scanner follows the same language as the elements of an image. Container scanning tools often use multiple Common Vulnerability and Exposure (CVE) databases to test if there are CVE’s within a container image.
13. Use fixed tags
Tags are used to indicate different versions of Docker images to make clear which version is the most recent and which have come before. However, version control can get confusing as the tags can be changed, meaning multiple images can have the same tag. The result is that automated builds can get disrupted.
To ensure that the tags remain fixed, consider using a private key to cryptographically sign images to guarantee that no changes are made to the image or tag. Or save a copy of the image in a private repository to that can be referred to if any verification is needed. Finally, use more detailed tags, for example, include the operating system as well as the version.
14. Use caution with docker images and sensitive information
Docker images often require data such as credentials, TLS certificates, database names or SSH keys. Sensitive data may also be generated or stored by applications running in a container. This information should never be hardcoded into the Dockerfile because it can be stored in intermediate container layers. So, even if the container is deleted, the information can still be copied. There is a solution – secrets management capability whereby sensitive data can be managed at runtime without being stored in the source code or image.
15. Use private registries
Public container registries are convenient, but they also come with security risks and could unintentionally or intentionally be compromised. A private registry deployed behind the company’s firewall and with Role Based Access Control (RBAC) to restrict which users can upload and download images from it is safer.
16. Use multi-stage builds
Multi-stage builds are efficient and secure. Building containerized applications in this manner increases the control over files and artefacts that go into a container image, making it difficult for attackers to add malicious artefacts without permission.
17. Monitor container activity
Efficient control and clear monitoring are important to running containerized applications at the optimum level of performance. Dedicated cloud-native monitoring tools are best to scan for irregularities to then correct and rebuild faulty images.
18. Implement runtime security
Implement drift prevention measures to stop attacks in runtime and prevent zero-day exploits. Workloads are a key target for hackers, so securing the workload with runtime security for Docker containers will ensure that drift is not possible once the container is running and will immediately block any malicious action.
19. Maintain containers without direct access
Vulnerabilities can emerge when IT teams access containers using SSH for every maintenance task. Instead, teams should make logs available outside the container to be maintained without needing direct access. This limits SSH access while still enabling administrators to troubleshoot and replace containers.
- Cybersecurity: the crucial double check
- Creating a cybersecurity culture in the workplace
- 8th worst in Europe: Cybersecurity for UK business
- Confused about data governance, privacy & security?
20. Use metadata
Labelling is used to organize containers and include further details to containers including authors, licensing details, container origin and history. To avoid labelling errors, consider using automated labelling and restrict user permissions when assigning who can change and allocate labels.