How To Secure Your Docker Containers: The Most Essential Steps
Essential security practices to protect your Docker containers from vulnerabilities, misconfigurations, and cyber threats.
Introduction
Often, I got asked by developers or system administrators how I securely run Docker containers and what best practices I follow. I know ensuring container security is very important because misconfigurations and vulnerabilities can expose our system to attacks and that is not what we want.
Because of this, I wanted to create this article explaining possible attack vectors and then cover the most essential steps to secure Docker environments preventing attackers from using them.
Have Fun Reading!
Understanding Potential Attack Vectors
Before we can dive into security measures, we should be able to recognize the most common attack vectors that threaten our Docker environments.
- Insecure Exposure: One of the most frequent risks occurs when users expose the Web UI of applications without implementing proper security controls, making them an easy target for attackers.
- Unverified or Malicious Images: If we run container images from untrusted sources, such as third-party application catalogs that have little to no transparency about their creators or source code, we could introduce security risks.
- Supply Chain Attacks: Still, if we use a trusted image, some dependencies within it may contain malicious code, which could lead to a potential compromise.
- Lateral Movement: If a device or a container within our network gets infected, an attacker can exploit it to move from it to other devices and gain access to your server through vulnerable applications.
- Vulnerabilities and Bugs: Any containerized application that we deploy can have security flaws. This means there could be some vulnerabilities which are exploitable, leading to serious consequences.
Key Security Practices to Mitigate Risks
To minimize the security risks for our Docker container we can simply follow these best practices:
✔ Carefully Vet Image Sources: We should always use official or well-reviewed repositories and verify the integrity of the image before deployment.
✔ Keep Containers Updated, But Avoid Auto-Updates: We have to update our containers regularly and help patch vulnerabilities. However, we should avoid automated updates because they can introduce breaking changes.
✔ Enforce the Least Privilege Principle: We should limit permissions for our containers, only permitting what is necessary and preventing unnecessary access.
✔ Restrict Container Resources: CPU, memory, and storage limits should be used to prevent resource exhaustion attacks.
✔ Do Regular Backups: If a breach, a failure, or anything else happens, it is very important that we have done recent backups to ensure a quick recovery without losing too much data.
All of the mentioned security practices should offer us a strong foundation for protecting our Docker environment. Although this list doesn't cover every measure, it should highlight the most critical parts that are easy to implement and very effective. Normally, these steps could also be implemented by people with limited technical expertise.
Key Docker Security Practices Explained
To keep it simple and more importantly practical, I have created a list of the most important security practices which are very easy to implement. This list is primarily focused on helping the less technical Docker enthusiasts strengthen their container security without getting frustrated by all the complex configurations. As mentioned above the list is not complete but should include the most important steps.
1. Use Trusted Image Sources
If we are running container images from unverified or unknown sources we will introduce a significant security risk, because many contain malware, outdated software, or vulnerabilities that could be exploited by attackers.
To avoid this, we should:
- Always pull images from official repositories (like Docker Hub) or well-maintained sources with a strong reputation.
- Check its source code, update history, and overall trust level
- Check factors such as popularity (stars, downloads), contributor activity, and release frequency.
- Avoid running images that lack transparency about their origin or maintenance status.
2. Keep Your System and Containers Updated
An updated system is very important! Because of that regular updates for our containers help us to protect against newly discovered vulnerabilities. BUT, we should never blindly update to the newest version because the new version could introduce bugs or breaking changes.
We should always:
- Frequently update our host operating system, Docker engine, and container images to benefit from the latest security patches.
- Avoid automatic updates for containers. They can unintentionally pull compromised or broken images before issues are identified. Also, new images can introduce breaking changes like database upgrades (switching from SQLite to MySQL), changes in communications, or changing base functionality (Remove SHA1 for support for SSH RSA signing - Gitea some time ago...)
- Verify the stability and security of the new version and update manually.
3. Protect the Docker Socket
The Docker socket (/var/run/docker.sock
) is a very critical part of our Docker environment that grants full control over the Docker daemon. Exposing it without cautions can lead to severe security breaches.
- Never mount the Docker socket directly into our containers. If we do it we could allow attackers inside a compromised container to control our entire host system.
- There is a common misconception that mounting the socket as read-only improves security but it does not. Attackers are still able to execute commands and escalate privileges.
- We should use a Docker socket proxy with minimal privileges. Using this approach only a designated, well-audited container can interact with the Docker API, reducing overall exposure.
4. Disable Privilege Escalation
By default, in many containers, it is possible that we can use sudo
doas
, and suid
with could allow processes to gain additional privileges which increase the risk of exploitation.
We should prevent privilege escalation inside any containers by adding the following security option to the Compose file:
security_opt:
- no-new-privileges=true
This setting prevents the use of sudo
, doas
, and suid
which will reduce the risk for privilege-related attacks. However, it could be that some images may require these privileges to work properly. This means, that we have to test this setting beforehand.
5. Restrict Dangerous Privileges and Capabilities
Docker containers normally run with a limited set of capabilities that control what they can and cannot do on the host system. Granting more privileges will increase the security risk.
Because of this, we should:
- Avoid using the
--privileged
flag! This will give our container almost the same level of access as the host itself. Using this setting will grant an attacker nearly full control over our host system - Not granting elevated capabilities such as
SYS_ADMIN
to our Docker containers. This setting will effectively allow a container to bypass most security restrictions and take over the host. - Always use only the minimal set of privileges for the container to function correctly.
6. Run Containers as a Non-Root User
To limit the potential damage an attacker can do if any container is compromised we should run all containers as non-root users. This means that instead of granting root privileges we should use PUID/PGID
or explicitly define a user to reduce the risk in our Compose file:
somecontainer:
environment:
- PUID=1000
- PGID=1000
othercontainer:
user: "1000:1000"
7. Set Resource Limits
If not correctly managed, Docker containers could monopolize system resources and cause performance issues due to memory leaks. To prevent this, we should enforce resource constraints in our Docker Compose file.
In the following Compose file we can see how Docker Compose anchors are used to define a base configuration and then override the values as needed for individual containers (explained in comments):
# Define a reusable configuration block using an anchor (&base)
x-base: &base
mem_limit: 1000m # Limit container memory usage to 1000 MB (1GB)
pids_limit: 200 # Restrict the container to a maximum of 200 processes
cpus: "2" # Restrict CPU usage to 2 cores (prevents overuse)
logging:
options:
max-size: "10m" # Each log file will be max 10MB in size
max-file: "3" # Keep up to 3 log files (rotates old ones)
security_opt:
- no-new-privileges=true # Prevents privilege escalation inside the container
# Define containers that will be deployed
services:
somecontainer:
<<: *base # Apply the base configuration to this container
environment:
- PUID=1000
- PGID=1000
anothercontainer:
<<: *base # Apply the base configuration to this container
environment:
- PUID=1000
- PGID=1000
If we set these limits in our containers we can ensure that they cannot consume excessive CPU, memory, or storage which will prevent potential system crashes or slowdowns.
Since I encountered that one container created such an enormous amount of logs that my cluster broke I always use log rotation. You can read about the problem in this article:

8. Regular Backups
Backups are very important and are essential for recovering after security breaches, data loss, or a system failure. If this happens it is a big problem and not having backups could really hurt us.
Because of this, we should:
- Back up our Docker Compose files and container data volumes regularly (ideally in a GIT).
- Use application-provided backup tools (e.g. PostgreSQL and MariaDB)
- Use a backup solution like Velero, Duplicati, rsync, etc.
- Be aware that some applications cannot be backed up while running, so we have to check their documentation for best practices.
Using a good backup strategy will ensure that we can recover quickly from an incident which will minimize the downtime and prevent data loss.
As you might now, I learned that the hard way that backups are very important. You can read about my incident here:

Closing Notes
Now, that we have reached the end of the article I want to highlight a very important statement:
Security Is an Ongoing Process
This means, that security isn't just about following a simple checklist. It requires understanding our threat model and continually improving our defenses.
My personal tips for everyone are, that we should:
- Stay informed about new security vulnerabilities affecting Docker and all applications we use. For me, I use FreshRSS to subscribe to popular security-related websites and read all important articles.
- Regularly review and refine our Docker security practices.
- Accept that no system is 100% secure. But we should take proactive steps to significantly reduce risks.
By doing this, we can keep our Docker environment more secure against possible threats.
I hope you find these Docker security tips helpful and can easily adopt these best practices for yourself. Also, I would love to hear your ideas and thoughts about these tips. If you can provide more best practices to implement, don’t hesitate to comment here. If you have any questions, please write them down below. I try to answer them if possible.
Feel free to connect with me on Medium, LinkedIn, Twitter, BlueSky, and GitHub.
🙌 Support this content
If you like this content, please consider supporting me. You can share it on social media, buy me a coffee, or become a paid member. Any support helps.
See the contribute page for all (free or paid) ways to say thank you!
Thanks! 🥰