Secure Docker Configurations
This guide provides security best practices for Dockerfiles and docker-compose configurations. Following these patterns helps prevent container escapes, privilege escalation, and other security vulnerabilities in containerized environments.
Running as Root
The last user in the container should not be 'root'. If an attacker gains control of the container, they will have root access.
Incorrect:
FROM debian:bookworm
RUN apt-get update && apt-get install -y some-package
USER appuser
USER rootCorrect:
FROM debian:bookworm
USER root
RUN apt-get update && apt-get install -y some-package
USER appuserMissing Image Version
Images should be tagged with an explicit version to produce deterministic container builds.
Incorrect:
FROM debianCorrect:
FROM debian:bookwormUsing Latest Tag
The 'latest' tag may change the base container without warning, producing non-deterministic builds.
Incorrect:
FROM debian:latestCorrect:
FROM debian:bookwormPrivileged Mode (Docker Compose)
Running containers in privileged mode grants the container the equivalent of root capabilities on the host machine. This can lead to container escapes, privilege escalation, and other security concerns.
Incorrect:
version: "3.9"
services:
worker:
image: my-worker-image:1.0
privileged: trueCorrect:
version: "3.9"
services:
worker:
image: my-worker-image:1.0
privileged: falseExposing Docker Socket
Exposing the host's Docker socket to containers via a volume is equivalent to giving unrestricted root access to your host. Never expose the Docker socket unless absolutely necessary.
Incorrect:
version: "3.9"
services:
worker:
image: my-worker-image:1.0
volumes:
- /var/run/docker.sock:/var/run/docker.sockCorrect (use a named volume instead of host mounts):
version: "3.9"
services:
worker:
image: my-worker-image:1.0
volumes:
- worker-data:/app/data
volumes:
worker-data:Arbitrary Container Run (Python Docker SDK)
If unverified user data can reach the run or create method, it can result in running arbitrary containers.
Incorrect:
import docker
client = docker.from_env()
def run_container(user_input):
client.containers.run(user_input, 'echo hello world')Correct:
import docker
client = docker.from_env()
def run_container():
client.containers.run("alpine", 'echo hello world')