[Webinar] Don't let your IaC platform become another system to maintain |

Sign up ➡️

Docker

21 Docker Security Best Practices: Daemon, Image, Containers

Docker Security Best Practices

Docker is the most popular containerization platform. It isolates software and its dependencies into self-contained units that run independently of your host machine.

Docker’s isolation model can enhance the security of your containerized workloads. Separating applications into containers makes it harder for errant processes to influence each other. However, Docker can also pose new security risks if you don’t properly harden your environment. Hardening it is what keeps that isolation from becoming a liability.

In this guide, we’ll share some best practices for improving Docker security. Docker security comes down to hardening three layers: the Docker daemon, the images you build, and the containers you run. The practices below cover all three, from disabling the daemon’s TCP socket and running rootless, to scanning and signing images, to dropping Linux capabilities and running containers as a non-root user.

We will cover:

  1. Docker daemon security
  2. Docker image security
  3. Docker container security

TL;DR

Docker’s isolation model improves security by default, but it doesn’t harden itself. Real protection comes from securing three layers:

 

  • Daemon: keep the socket off the network, run rootless, stay patched, and leave SELinux, Seccomp, and AppArmor on.
  • Images: use trusted, minimal bases (Docker Hardened Images cut CVEs), rebuild often, scan with Docker Scout or Trivy, and sign with Cosign or Notation.
  • Containers: run as non-root, drop unneeded capabilities, avoid privileged mode, set no-new-privileges, use read-only filesystems, and cap resources.

Docker daemon security best practices

Docker’s architecture is daemon-based: the client CLI you interact with communicates with a separate background service to carry out actions such as building images and starting containers. It’s critical to protect the daemon because anyone with access to it can execute Docker commands on your host.

Docker daemon security best practices include:

  1. Don’t expose the Docker daemon socket
  2. Use TLS if you must expose the daemon socket
  3. Enable rootless mode where possible
  4. Keep Docker updated
  5. Disable inter-container communication
  6. Enable OS-level security protections (SELinux/Seccomp/AppArmor)
  7. Harden your host
  8. Enable user namespace remapping

1. Don't expose the Docker daemon socket

The Docker daemon is normally exposed via a Unix socket at /var/run/docker.sock. It’s possible to optionally configure the daemon to listen on a TCP socket too, which allows remote connections to the Docker host from another machine.

This should be avoided because it presents an additional attack vector. Accidentally exposing the TCP socket on your public network would allow anyone to send commands to the Docker API, without first requiring physical access to your host. Keep TCP disabled unless your use case demands remote access.

2. Use TLS if you must expose the daemon socket

When there’s no alternative to using TCP, it’s essential to protect the socket with TLS. This will ensure access is only granted to clients that present the correct certificate key.

TCP with TLS is still a potential risk because any client with the certificate can interact with Docker. It’s also possible to use an SSH-based connection to communicate with the Docker daemon, which allows you to reuse your existing SSH keys.

3. Enable rootless mode where possible

Docker defaults to running both the daemon and your containers as root. This means that vulnerabilities in the daemon or a container could allow attackers to breakout and run arbitrary commands on your host.

Rootless mode is an optional feature that allows you to start the Docker daemon without using root. It’s more complex to set up and has some limitations, but it provides a useful extra layer of protection for security-sensitive production environments.

4. Keep Docker updated

One of the easiest ways to maintain Docker security is to stay updated with new releases. Docker regularly issues patches that fix newly found security problems. Running an old version makes it more likely that you’re missing protections for exploitable vulnerabilities.

Regularly apply any updates offered by your OS package manager to ensure you’re protected. 

5. Disable inter-container communication

Docker normally allows arbitrary communication between the containers running on your host. Each new container is automatically added to the docker0 bridge network, which allows it to discover and contact its peers.

Keeping inter-container communication (ICC) enabled is risky because it could permit a malicious process to launch an attack against neighboring containers. You should increase your security by launching the Docker daemon with ICC disabled (using the --icc=false flag), then permit communications between specific containers by manually creating networks.

6. Enable OS-level security protections (SELinux/Seccomp/AppArmor)

Ensuring OS-level security systems are active helps defend against malicious activity originating inside containers and the Docker daemon. Docker supports policies for SELinux, Seccomp, and AppArmor; keeping them enabled ensures sane defaults are applied to your containers, including restrictions for dangerous system calls.

7. Harden your host

Docker security is only as good as the protection surrounding your host. You should fully harden your host environment by taking steps such as regularly updating your host’s OS and kernel, enabling firewalls and network isolation, and restricting direct host access to just the administrators who require it.

Neglecting basic security measures will undermine the strongest container protections.

8. Enable user namespace remapping

User namespace remapping is a Docker feature that converts host UIDs to a different unprivileged range inside your containers. This helps to prevent privilege escalation attacks, where a process running in a container gains the same privileges as its UID has on your host.

User namespace remapping assigns the container a range of UIDs from 0 to 65536 that translate to unprivileged host users in a much higher range. To enable the feature, you must start the Docker daemon with a --userns-remap flag that specifies how the remapping should occur. Some container features aren’t compatible with remapping, but it’s worth enabling it whenever possible.

Docker image security best practices

Once you’ve tightened the security around your Docker daemon installation, it’s important to also review the images that you use. A compromised image can harbor security threats that form the basis of a successful attack.

Docker image security best practices include:

  1. Use trusted/minimal base images
  2. Regularly rebuild your images
  3. Use image vulnerability scanners
  4. Sign and verify image authenticity
  5. Lint your Dockerfiles to detect unsafe misconfigurations

1. Use trusted/minimal base images

Only select trusted base images for the FROM instructions in your Dockerfiles. You can easily find these images by filtering using the “Docker Official Image” and “Verified Publisher” options on Docker Hub. An image that’s published by an unknown author or which has few downloads might not contain the content you expect.

It’s also advisable to use minimal images (such as Alpine-based variants) where possible. These will have smaller download sizes and should contain fewer OS packages, which reduces your attack surface.

Docker Hardened Images (DHI) are a newer option worth knowing. These are minimal, near-zero-CVE base images that Docker rebuilds continuously from source. They became free and open source under the Apache 2.0 license in December 2025 and are available from dhi.io. Runtime variants are distroless and run as a non-root user by default, with no shell or package manager, so they cut your attack surface further than a standard Alpine or Debian base.

2. Regularly rebuild your images

Regularly rebuild your images from your Dockerfiles to ensure they include updated OS packages and dependencies. Built images are immutable, so package bug fixes and security patches released after your build won’t reach your running containers.

Periodically rebuilding your images and restarting your containers is the best way to prevent stale dependencies being used in production. You can automate the container replacement process by using a tool such as Watchtower.

3. Use image vulnerability scanners

Scanning your built images for vulnerabilities is one of the most effective ways to inform yourself of problems. Scan tools are capable of identifying which packages you’re using, whether they contain any vulnerabilities, and how you can address the problem by upgrading or removing the package.

You can perform a scan by running the docker scout command (previously docker scan) or an external tool such as Anchore or Trivy. Scanning each image you build will reveal issues before the image is used by containers running in production. It’s a good idea to include these scans as jobs in your CI pipeline.

Modern scanners, including Docker Scout, can also generate a software bill of materials (SBOM) for each image, which gives you an auditable inventory of everything shipping inside it.

4. Sign and verify image authenticity

Before you run a container, confirm the image is authentic and hasn’t been tampered with in your registry or in transit. Image signing lets publishers sign what they build, and consumers verify that signature before pulling.

Docker Content Trust, the original Notary v1 signing mechanism, is now retired. Docker began retiring it for Docker Official Images in August 2025 and has since shut down the Notary v1 service at notary.docker.io, so setting DOCKER_CONTENT_TRUST=1 no longer works for those images. Use OCI-native tooling instead: Sigstore’s Cosign or the Notary Project’s Notation both store signatures alongside the image in any compliant registry, with no separate trust server to run.

Sign images during your build, verify signatures in your CI pipeline, and enforce verification before deployment.

5. Lint your Dockerfiles to detect unsafe misconfigurations

Linting your Dockerfiles before you build them is an easy way to spot common mistakes that could pose a security risk. Linters such as Hadolint check your Dockerfile instructions and flag any issues that contravene best practices.

Fixing detected problems before you build will help ensure your images are secure and reliable. This is another process that’s worth incorporating into your CI pipelines.

Docker container security best practices

The settings you apply to your Docker containers at runtime affect the security of your containerized applications, as well as your Docker host. Here are some techniques that help prevent containers from posing a threat.

Docker container security best practices include:

  1. Don’t expose unnecessary ports
  2. Don’t start containers in privileged mode
  3. Drop capabilities when you start containers
  4. Set up container resource quotas
  5. Ensure container processes run as a non-root user
  6. Prevent containers from escalating privileges
  7. Use read-only filesystem mode
  8. Use a dedicated secrets manager

1. Don't expose unnecessary ports

Exposing container ports unnecessarily (using the -p or --port flag for docker run) can increase your attack surface by allowing external processes to probe inside the container. Only ports which are actually needed by the containerized application (typically those listed as Dockerfile EXPOSE instructions) should be opened.

Read more about exposing Docker ports.

2. Don't start containers in privileged mode

Using privileged mode (--privileged) is a security risk that should be avoided unless you’re certain it’s required. Containers that run in privileged mode are granted all available Linux capabilities and have some cgroups restrictions lifted. This allows them to achieve almost anything that the host machine can.

Containerized apps very rarely require privileged mode. It’s typically only useful when you’re running an application that needs full access to your host or the ability to manage other Docker containers.

3. Drop capabilities when you start containers

Even the default set of Linux capabilities granted by Docker can be too permissive for production use. They include the ability to change file UIDs and GIDs, kill processes, and bypass file read, write, and execute permission checks.

It’s good practice to drop capabilities that your container doesn’t need. The docker run command’s --cap-drop and --cap-add flags allow you to remove and grant them. The following example drops every capability, then adds back CHOWN to permit file ownership changes:

$ docker run --cap-drop=ALL --cap-add=CHOWN example-image:latest

4. Set up container resource quotas

Docker doesn’t automatically apply any resource constraints to your containers. Containerized processes are free to use unlimited CPU and memory, which could impact other applications on your host. Setting limits for these resources helps to defend against denial-of-service (DoS) attacks.

Limit a container’s memory allowance by including the -m or --memory flag with your docker run commands:

$ docker run -m=128m example-image:latest

To set a CPU allowance, supply the --cpus flag. You must specify the number of CPU cores you want to make available:

$ docker run --cpus=2 example-image:latest

More precise options are supported for both of these resource constraints.

5. Ensure container processes run as a non-root user

Containers default to running as root but this can be changed by either including a USER instruction in your Dockerfile or setting the docker run command’s --user flag:

$ docker run --user=1000 example-image:latest

Either of these methods ensure your container will execute as a specific non-root user. This minimizes the risk of container breakout attacks by preventing the containerized process from running commands as root on your host.

6. Prevent containers from escalating privileges

Containers can usually escalate their privileges by calling the setuid and setgid binaries. This is a security risk because the containerized process could use setuid to effectively become root.

To prevent this, you should set the no-new-privileges security option when you start your containers:

$ docker run –security-opt=no-new-privileges:true example-image:latest

When this flag is used, calls to setuid and setgid will have no effect. This prevents the container from acquiring new privileges.

7. Use read-only filesystem mode

Few containerized applications need to write directly to their filesystem. Opting them into Docker’s read-only mode prevents filesystem modifications, except to designated volume mount locations. This will block an intruder from making malicious changes to the content within the container, such as by replacing binaries or configuration files.

$ docker run --read-only example-image:latest

8. Use a dedicated secrets manager

Sensitive data required by your containers, such as API keys, tokens, and certificates, should be stored in a dedicated secrets management solution. This reduces the risk of accidental exposure that arises when environment variables or regular config files are used.

For the best protection, you should adapt your application to read secrets from a separate platform, such as a HashiCorp Vault deployment, which is also integrated with Spacelift. This ensures your secrets are kept safe, independently of your source code, container deployments, and Docker host machine.

Container security ends where your Dockerfile does. Everything past that point, the registry, the cluster, the roles, and the network, is infrastructure as code that changes weekly. 

Spacelift runs those changes through a GitOps workflow with Open Policy Agent (OPA) policies, so a failed scan or a public registry blocks the run instead of reaching production. You can wire any scanner into a policy decision with Custom Inputs, pin the Docker runner image every run executes in, and keep credentials on your own network with private workers.

Book a demo or start for free.

Key takeaways

If you apply only a few of these, start with three: run the daemon and your containers rootless, run container processes as a non-root user, and scan every image before it reaches production. These three close off the most common paths to container breakout and privilege escalation, and everything else in this guide builds on them.

Taking steps to harden your Docker environment is critical to maintaining good security for your containers, applications, and host machine. In this guide, we’ve covered some key steps you can take to secure the Docker daemon, create safer images, and protect containers at runtime.

Relatively simple measures such as regularly updating Docker and using Docker secrets for sensitive values can significantly improve your overall security posture. Keep these tips in mind to safeguard your environment, then learn more about Docker by reading our other articles on the Spacelift blog

Solve your infrastructure challenges

Spacelift is a flexible orchestration solution for IaC development. It delivers enhanced collaboration, automation, and controls to simplify and accelerate the provisioning of cloud-based infrastructures.

Start free trial

Frequently asked questions

  • Is Docker in Docker secure?

    Running Docker in Docker (DinD) is not considered secure for production. It grants the inner container full control over the Docker daemon on the host, effectively bypassing isolation. This can lead to container breakout, privilege escalation, and unintended access to host resources. DinD is best suited for CI environments where isolation is tightly controlled.

  • Does Docker have a firewall?

    No. Docker does not ship a standalone firewall and instead programs the host firewall on Linux using iptables, including the DOCKER and DOCKER-USER chains.

  • Is Kubernetes more secure than Docker?

    Kubernetes is not inherently more secure than Docker, but it provides more advanced security controls at scale.

Docker CLI Commands Cheat Sheet

Grab our ultimate cheat sheet PDF

for all the Docker commands you need.

docker book
Share your data and download the cheat sheet