
Lab 011 - Docker Security & Trust¶
- This lab covers advanced Docker security features and best practices for container security and privilege management.
- You’ll learn about reducing the attack surface, implementing the Principle of Least Privilege, and using Docker’s security mechanisms to protect your containers.
- Topics include non-root user execution, Linux capabilities, security options, and mandatory access control.
- By the end of this lab, you’ll understand how to build and run secure Docker containers.
Table of Contents¶
- 🛡️ Non-Root User Execution with the
USERInstruction - How to Use
USER - 🔒 Advanced Security Issues and Features
- 1. Privileged Containers (
--privileged) - 2. Linux Capabilities (
--cap-drop,--cap-add) - 3. Preventing Privilege Escalation
- 4. Mandatory Access Control (MAC)
- 5. User Namespace Remapping (UserNS)
- 🔑 Summary of Security Best Practices
- Docker’s advanced features offer critical mechanisms for container security and privilege management, primarily revolving around reducing the attack surface.
- The key is to adhere to the Principle of Least Privilege (PoLP).
🛡️ Non-Root User Execution with the USER Instruction¶
- By default, the process inside a Docker container runs as the
root user (UID 0), which is a major security risk. - If an attacker successfully exploits a vulnerability in the application, they gain root access inside the container.
- Depending on the container’s configuration and any underlying kernel vulnerabilities, this could potentially lead to a container breakout and root access to the host machine.
- The
USERinstruction in aDockerfileis essential for mitigating this risk:
How to Use USER¶
- Create a Non-Root User
- Use a
RUNinstruction to create a dedicated user and group before switching the user.# Create an unprivileged user (e.g., 'appuser' with UID 1001) RUN adduser -D appuser # Set the ownership of the application directory to the new user RUN mkdir /app && chown -R appuser:appuser /app # Switch to the non-root user for all subsequent instructions and runtime USER appuser WORKDIR /app # ... rest of your application commands (e.g., CMD)
adduser -D
Using adduser -D (on Alpine) creates a system user without a password or home directory, which is more secure.
Best Practices for Permissions:¶
-
File Permissions¶
- Ensure the non-root user has the necessary read, write, and execute permissions for all files, directories, or temporary spaces the application needs.
- This often requires running
chownin the Dockerfile.
-
Multi-Stage Builds¶
- Use multi-stage builds to perform privileged operations (like installing system packages with
aptoryum) in a “builder” stage run as root, and then copy only the necessary artifacts into a minimal, non-root “runtime” stage. - This prevents residual root tools or sensitive build-time files from existing in the final image.
- Use multi-stage builds to perform privileged operations (like installing system packages with
-
Bind Ports > 1024¶
- Only the root user can bind to privileged ports (0-1023).
- If your application runs as non-root, it must bind to ports 1024 or higher (e.g., port 8080).
-
User¶
- Always specify a non-root user with the
USERinstruction in your Dockerfile to prevent running as root. - Avoid using
sudoinside containers; instead, configure permissions properly at build time. - Consider using well-known non-root users like
- Always specify a non-root user with the
-
Privileged Containers¶
- Avoid running containers with the
--privilegedflag, as it grants excessive permissions and can lead to host compromise. - Instead, use specific capability additions (
--cap-add) if certain elevated privileges are necessary. - Always review and minimize the capabilities your container needs.
- Consider using tools like
seccompto restrict system calls your container can make.
- Avoid running containers with the
🔒 Advanced Security Issues and Features¶
- Beyond running as a non-root user, Docker provides several advanced features to lock down container security:
1. Privileged Containers (--privileged)¶
-
A privileged container is the most dangerous security configuration and should be avoided at all costs unless absolutely necessary (e.g., for running Docker-in-Docker or a tool that needs to interact directly with the host kernel).
-
Security Issue:
- Running a container with the
--privilegedflag grants it all Linux Capabilities (see below) and allows it to access all devices on the host. In a privileged container, the root user inside the container is essentially equivalent to the root user on the host machine. A container breakout is almost guaranteed. - Mitigation: NEVER use
--privilegedin production.
Instead, identify the specific capabilities your application needs and grant only those using the--cap-addflag.
- Running a container with the
2. Linux Capabilities (--cap-drop, --cap-add)¶
- Linux Capabilities are a finer-grained way to manage root permissions.
- Traditional Unix divides processes into two categories: root (UID 0) and unprivileged.
-
Capabilities break down the powers of the root user into discrete units.
-
By default, Docker grants a set of “safe” capabilities and drops dangerous ones.
- Best Practice: Use the
--cap-drop=ALLflag to remove all capabilities, then use--cap-addto grant only the handful that the application truly requires (PoLP).
3. Preventing Privilege Escalation¶
-
Even if a container starts as non-root, a malicious process could attempt to escalate its privileges.
-
no-new-privileges: Use the--security-opt=no-new-privilegesflag to prevent a process from gaining new privileges via mechanisms likesetuidorsetgidbinaries. This is a crucial security layer.
4. Mandatory Access Control (MAC)¶
- Docker integrates with two major Linux security modules for deeper kernel-level protection:
| Feature | Description | Purpose |
|---|---|---|
| Seccomp (Secure Computing) | Filters which system calls (syscalls) a container process can make to the Linux kernel. | Blocks dangerous syscalls that could be used for container breakout, even if the process is running as root. Docker uses a restrictive default profile. |
| AppArmor (Application Armor) | Creates Mandatory Access Control (MAC) profiles that limit what files, network resources, and other capabilities a container can access. | Provides an extra layer of defense-in-depth by confining the container process’s access to host resources. Docker loads a moderately protective docker-default profile. |
5. User Namespace Remapping (UserNS)¶
-
This is one of the strongest isolation features for mitigating the risk of a container breakout.
-
How it Works: It maps the root user (UID 0) inside the container to an unprivileged user (a high UID, e.g., 100000) on the host machine.
- Security Benefit: If an attacker does manage to escape the container, they only have the privileges of the unprivileged mapped user on the host, not actual root access. This significantly reduces the potential for host compromise. This feature can be enabled at the Docker daemon level.
🔑 Summary of Security Best Practices¶
| Security Principle | Docker Feature/Instruction | Impact |
|---|---|---|
| Least Privilege | USER non-root in Dockerfile | Prevents an exploit from gaining root access inside the container. |
| Runtime Hardening | --cap-drop=ALL, --cap-add=<needed-caps> | Removes unnecessary superuser powers, reducing the attack surface. |
| Kernel Isolation | Seccomp/AppArmor | Limits the dangerous operations (syscalls, file access) a process can perform. |
| No Escalation | --security-opt=no-new-privileges | Prevents a non-root process from gaining root powers during execution. |
| Host Protection | User Namespace Remapping | Ensures that an escaped container process runs as an unprivileged user on the host. |
Running the Demos¶
This lab includes individual demo scripts for each security topic:
| Demo Script | Description |
|---|---|
demo1-nonroot.sh | Demonstrates non-root user execution |
demo2-capabilities.sh | Shows Linux capabilities management |
demo3-security-options.sh | Demonstrates security options like no-new-privileges |
demo4-mac.sh | Checks Mandatory Access Control (Seccomp/AppArmor) status |
demo5-userns.sh | Explores User Namespace Remapping configuration |
To run a demo:
Each demo is self-contained with automatic cleanup.