Docker Security Guidelines

Adhere to these guidelines to ensure the security and integrity of your Docker environment, from keeping your software up-to-date to configuring your containers and networks securely.

RULE 1 – Keep Host & Docker Up to Date

Regularly patch Docker Engine and Docker Machine to prevent container escape vulnerabilities, which can lead to root/administrator privilege escalation. Containers share the kernel with the host, so kernel exploits inside a container directly impact the host kernel. For example, a kernel privilege escalation exploit like Dirty COW executed inside a container results in root access on the host.

RULE 2 - Do Not Expose the Docker Daemon Socket

The Docker socket /var/run/docker.sock is the primary entry point for the Docker API and is owned by root. Giving access to this socket is equivalent to giving unrestricted root access to the host. Do not enable the tcp Docker daemon socket. Running the Docker daemon with -H tcp://0.0.0.0:XXX or similar exposes unencrypted and unauthenticated direct access to the Docker daemon. If absolutely necessary, secure it following Docker's official documentation. Do not expose /var/run/docker.sock to other containers. Avoid running Docker images with -v /var/run/docker.sock://var/run/docker.sock. Mounting the socket read-only only makes exploitation harder but does not resolve the issue. In a docker-compose file, it looks like:

Copy

Yaml

volumes:
  - "/var/run/docker.sock:/var/run/docker.sock"

RULE 3 - Run Docker Containers as Non-Root Users

By default, Docker containers run as root users. Running applications inside Docker containers as root poses a significant security threat, especially when deploying applications at scale. If an application inside a container is compromised, other applications and the entire network are at risk. To mitigate this, ensure Docker containers run as non-root users.

  1. Adding a User to the Docker Group: Create a Docker group if it does not exist:

    Copy
    sudo groupadd docker

    Add non-root users to the Docker group:

    Copy
    sudo usermod -aG docker [non-root user]

    Re-login to Docker to verify group membership.

  1. Using a Dockerfile:

    Specify non-root user instructions in the Dockerfile:

    Copy
    Pull the base image as Ubuntu 
    FROM ubuntu:latest 
    #Add a user with userid 8877 and name nonroot 
    RUN useradd −u 8877 nonroot 
    #Run Container as nonroot 

    USER nonroot 

    In Kubernetes, configure this in Security Context using the runAsNonRoot field:

    Copy
    kind: ...
    apiVersion: ...
    metadata:
      name: ...
    spec:
      containers:
      - name: ...
        image: ....
        securityContext:
          runAsNonRoot: true

    As a Kubernetes cluster administrator, configure it using Pod Security Policies.

RULE 4 - Limit Capabilities

Linux kernel capabilities are a set of privileges that can be granted to processes. Docker runs with a subset of capabilities by default. Use --cap-drop to drop capabilities and --cap-add to add necessary ones. Avoid running containers with the --privileged flag, as it adds all Linux kernel capabilities to the container. For a secure setup, drop all capabilities and then add only the required ones:

Copy
docker run --cap-drop all --cap-add CHOWN alpine

In Kubernetes, configure this in Security Context using the capabilities field:

Copy
kind: ...
apiVersion: ...
metadata:
  name: ...
spec:
  containers:
  - name: ...
    image: ....
    securityContext:
      capabilities:
        drop:
          - all
        add:
          - CHOWN

For more information, refer to Kubernetes documentation for configuring Pod Security Policies.

RULE 5 - Add No-New-Privileges Flag

Run Docker images with --security-opt=no-new-privileges to prevent privilege escalation using setuid or setgid binaries. In Kubernetes, configure this in Security Context using the allowPrivilegeEscalation field:

Copy
kind: ...
apiVersion: ...
metadata:
  name: ...
spec:
  containers:
  - name: ...
    image: ....
    securityContext:
      allowPrivilegeEscalation: false

For more information, refer to Kubernetes documentation for configuring Pod Security Policies.

RULE 6 - Disable Inter-Container Communication

By default, inter-container communication (icc) is enabled, allowing all containers to communicate with each other using the docker0 bridged network. Disable this by running the Docker daemon with the --icc=false flag. Specify allowed container communications using the --link=CONTAINER_NAME_or_ID:ALIAS option. See Docker documentation for more details. In Kubernetes, use Network Policies to manage container communication.

RULE 7 - Use Linux Security Modules (seccomp, AppArmor, or SELinux)

Do not disable the default security profile. Use AppArmor to restrict program capabilities with per-program profiles, and Seccomp to filter syscalls issued by a program. Follow Kubernetes API documentation for instructions on configuring security contexts using these modules.

RULE 8 - Limit Resources

To avoid DoS attacks, limit resources such as memory, CPU, file descriptors, and processes. For example:

Copy
docker run --memory 512m --cpus 2 --ulimit nofile=1024 --ulimit nproc=256

In Kubernetes, assign resources to containers and pods:

RULE 9 - Set Filesystem and Volumes to Read-Only

Run containers with a read-only filesystem using the --read-only flag:

Copy
docker run --read-only alpine sh -c 'echo "whatever" > /tmp'

Combine the --read-only flag with --tmpfs if temporary storage is needed:

Copy
docker run --read-only --tmpfs /tmp alpine sh -c 'echo "whatever" > /tmp/file'

In a docker-compose file:

Copy
version: "3"
services:
  alpine:
    image: alpine
    read_only: true

In Kubernetes, configure this in Security Context using the readOnlyRootFilesystem field:

Copy
kind: ...
apiVersion: ...
metadata:
  name: ...
spec:
  containers:
  - name: ...
    image: ....
    securityContext:
      readOnlyRootFilesystem: true

Mount volumes as read-only by appending :ro:

Copy
docker run -v volume-name:/path/in/container:ro alpine

Or using the --mount option:

Copy
docker run --mount source=volume-name,destination=/path/in/container,readonly alpine

RULE 10 - Use Static Analysis Tools

Detect containers with known vulnerabilities by scanning images with static analysis tools. Some recommended tools include:

For Kubernetes misconfigurations, use:

For Docker misconfigurations, use:

RULE 11 - Set the Logging Level to at Least INFO

Ensure the Docker daemon is set to a base logging level of 'info'. This level captures all important logs except debug logs, which should only be enabled when necessary. Configuring the log level to 'info' helps review crucial events later. Avoid running the Docker daemon at the 'debug' log level unless absolutely required.

To set the log level in docker-compose, use:

Copy
docker-compose --log-level info up

RULE 12 - Lint the Dockerfile at Build Time

Follow best practices when writing the Dockerfile to prevent issues. Add a security linter step in the build pipeline. Key checks include:

  • Ensure a USER directive is specified

  • Ensure the base image version is pinned

  • Ensure OS package versions are pinned

  • Avoid using ADD in favor of COPY

  • Avoid curl bashing in RUN directives

RULE 13 - Docker Security Operations: Docker Swarm Configuration

  • Enable swarm mode only if needed

  • Minimize the number of manager nodes in a swarm

  • Bind swarm services to a specific host interface

  • Encrypt container data exchange on different overlay network nodes

  • Manage secrets in a Swarm cluster with Docker's secret management commands

  • Run swarm manager in auto-lock mode

  • Rotate swarm manager auto-lock key periodically

  • Rotate node and CA certificates as needed

  • Separate management plane traffic from data plane traffic

RULE 14 - Run the Docker Daemon as a Non-Root User (Rootless Mode)

Rootless mode allows running the Docker daemon and containers as a non-root user, mitigating potential vulnerabilities in the daemon and the container runtime. Typically, creating namespaces and mounting filesystems require privileged capabilities, which historically required the Docker daemon to be started by the root user. Reduce the security footprint of the daemon and enable Docker for users without root privileges by referring to the Docker documentation:

Run Docker as rootless

References:

  • OWASP Docker Hardening guide