post 6:
You run containers every day.
But have you ever asked yourself this uncomfortable question:
If one container gets compromised… can it break out and take down the entire host?
Most people assume containers are “secure by default.”
They’re not.
They’re isolated by default — and isolation is not the same as security.
This post explains how Docker security actually works under the hood, what the real risks are, and how to harden your containers properly.
1. The Foundation: Linux Kernel Features
Docker doesn’t invent its own security model.
It relies heavily on existing Linux kernel features:
- Namespaces → Isolation of processes, network, filesystem, and more
- cgroups → Resource limits for CPU, memory, and I/O
- Capabilities → Fine-grained control over root privileges
- seccomp → Filtering of potentially dangerous system calls
- AppArmor / SELinux → Mandatory Access Control
Understanding these layers is the key to understanding container security.
2. Namespaces – Isolation, Not Security
Namespaces give each container its own private view of the system.
For example:
- PID namespace → Container processes are isolated from host processes
- Network namespace → Container gets its own network stack
- Mount namespace → Container gets its own filesystem view
- User namespace → Container users can be mapped to unprivileged users on the host
This isolation is powerful — but it isn't perfect.
All containers still share the same Linux kernel.
That means a serious kernel vulnerability could potentially affect the host and other containers.
Namespaces provide isolation, not complete security.
3. cgroups – Preventing Resource Exhaustion
Namespaces control what a container can see.
cgroups control how much of the host's resources it can consume.
Without resource limits, a single container could potentially:
- Consume excessive CPU
- Exhaust available memory
- Generate excessive disk I/O
For example:
docker run --memory=512m --cpus=1.0 nginx
Here:
-
--memory=512mlimits memory usage -
--cpus=1.0limits CPU usage
This helps prevent one container from consuming an unreasonable amount of the host's resources.
4. The Root Problem – Still Real
By default, many containers run as root (UID 0) inside the container.
However, Docker starts containers with a reduced set of Linux capabilities, limiting what that root process can do.
This significantly reduces the attack surface.
But container root is still something to take seriously.
If an application is compromised and has excessive privileges, combined with a kernel or runtime vulnerability, an attacker could potentially attempt a container escape.
A good practice is to run applications as a non-root user whenever possible.
For example, in a Dockerfile:
FROM nginx:alpine
USER 1000
Also avoid using:
--privileged
unless there is a specific, well-understood requirement.
The --privileged option grants a container significantly more access to the host and disables or weakens several isolation protections.
5. seccomp – Blocking Dangerous System Calls
seccomp (Secure Computing Mode) is another important Docker security layer.
Applications interact with the Linux kernel through system calls.
A compromised application could potentially try to use unusual or dangerous system calls to interact with the kernel.
Docker provides a default seccomp profile that blocks many system calls that containers typically don't need.
You can also apply a custom, stricter profile:
docker run \
--security-opt seccomp=/path/to/custom-profile.json \
nginx
This can further reduce the container's attack surface.
The key idea is simple:
If an application doesn't need a system call, don't give it access to that system call.
6. Rootless Docker – Reducing Host-Level Risk
Traditional Docker deployments commonly use a Docker daemon that requires root privileges.
This creates an important security consideration because access to the Docker daemon can provide powerful control over containers and, depending on configuration, the host.
Rootless Docker allows the Docker daemon and containers to operate without requiring root privileges.
Container root can be mapped to an unprivileged user on the host.
This reduces the potential impact of certain container or daemon compromises.
Rootless Docker is particularly useful in environments where reducing host-level privileges is important, although it can have some feature and compatibility limitations.
7. Practical Docker Hardening Checklist
Here are some practical steps you can apply:
- Run containers as a non-root user whenever possible
- Use official and regularly updated base images
- Enable Rootless Docker when it fits your environment
-
Use
--read-onlyfor the container filesystem when the application allows it -
Set resource limits such as
--memoryand--cpus - Keep Docker's default seccomp profile unless you have a reason to change it
- Use AppArmor or SELinux where appropriate
- Scan images regularly with tools such as Trivy or Docker Scout
-
Avoid
--privilegedunless there is a specific requirement - Keep Docker Engine and container images updated
Security is not achieved by using just one of these controls.
It comes from multiple layers working together.
Summary
Docker security is not magic.
It is a combination of multiple Linux and Docker security mechanisms:
- Namespaces → Process and resource isolation
- cgroups → Resource control
- Capabilities → Privilege reduction
- seccomp → System call filtering
- AppArmor / SELinux → Mandatory Access Control
- Rootless Docker → Reduced host-level privileges
Default Docker settings provide a useful level of isolation, but production environments often require deliberate security hardening.
The important thing to remember is:
Containers are isolated, but isolation alone does not make them secure.
Understanding what happens underneath Docker helps you move from:
“It works.”
to
“It works — and it’s properly secured.”
Next Topic
Docker Compose Internals – How It Orchestrates Multi-Container Applications
Top comments (0)