How to Secure Your Docker Containers: The Most Essential Steps

Photo edited by me from FlyD / Unsplash

How To Secure Your Docker Containers: The Most Essential Steps

Essential security practices to protect your Docker containers from vulnerabilities, misconfigurations, and cyber threats.

Paul Knulst  in  Docker Mar 19, 2025 8 min read

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.
💡
At the moment I am working on an article which explain how to use LinuxServer.io Docker Socket Proxy to secure a cluster. Subscribe to my newsletter to get it to your Inbox if it is published

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:

How To Manage Docker Logfiles with Logrotate
It is essential to configure log rotation for Docker containers. Log rotation is not performed by default, and if it’s not configured, logs on the Docker host can build up and eat up disk space. This guide will teach us how to set up Docker log rotation.

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:

Everybody Needs Backups - A Lesson Learned The Hard Way
A big incident within my Docker Swarm and the solution I developed after it occurred.

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 MediumLinkedInTwitter, 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! 🥰

By Paul Knulst

I'm a husband, dad, lifelong learner, tech lover, and Senior Engineer working as a Tech Lead. I write about projects and challenges in IT.