Learning objectives
By the end of this module, you should be able to:
- Explain why image provenance and updates matter.
- Apply basic least-privilege container controls.
- Recognize the risk of exposing the Docker Engine socket to a container.
Start with the image supply chain
Use trusted sources, pin intentional versions, rebuild regularly for security updates and scan images as part of delivery. A small image is not automatically secure, but fewer unnecessary packages can reduce attack surface.
Least privilege applies inside containers too
When the application does not require root, run it as a dedicated non-root user. Avoid --privileged unless you have a clear, reviewed requirement. Capabilities, read-only filesystems and targeted writable mounts can reduce what a compromised process can change.
The Docker socket is highly privileged
Mounting /var/run/docker.sock into a container effectively gives that container powerful control over the Docker host through the Engine API. Treat socket access as a privileged administrative capability, not a harmless convenience.
Worked examples
See the idea in practice.
Run with selected hardening controls
docker run --rm \
--read-only \
--cap-drop ALL \
--security-opt no-new-privileges \
alpine:3.20 id
- --read-only makes the container root filesystem read-only.
- --cap-drop ALL removes Linux capabilities; real applications may need a carefully selected subset.
- no-new-privileges prevents processes from gaining additional privileges through exec mechanisms such as setuid.
Inspect configured runtime user
docker image inspect nginx:alpine --format 'configured-user={{json .Config.User}}'
- An empty configured user generally means the image defaults to root unless runtime/user namespace behavior changes it.
- Do not assume every official image runs non-root.
Hands-on lab
Lab — Compare default and restricted execution
Goal: Observe how security controls change what a container can do.
STEP 1Default container can write its root filesystem
docker run --rm alpine:3.20 sh -c 'touch /root/demo && echo writable'
STEP 2Read-only root filesystem blocks the same write
docker run --rm --read-only alpine:3.20 sh -c 'touch /root/demo || echo write-blocked'
STEP 3Provide one explicit writable tmpfs path
docker run --rm --read-only --tmpfs /tmp alpine:3.20 sh -c 'touch /tmp/ok && echo tmp-writable; touch /etc/nope || echo etc-blocked'
STEP 4Drop capabilities for a simple process
docker run --rm --cap-drop ALL --security-opt no-new-privileges alpine:3.20 id
Verify
- The read-only container cannot write arbitrary root filesystem paths.
- An explicit tmpfs path can remain writable.
Expected outcome
- Security controls reduce writable surface without preventing a simple unprivileged command from running.
If it fails
- Real applications may require writable directories, capabilities or a specific UID. Add only what is required rather than disabling all controls wholesale.
- On SELinux systems, bind-mount labeling may need additional planning; do not relabel sensitive host trees casually.
Real-world connectionProduction container policies often combine non-root users, restricted capabilities, read-only filesystems, controlled mounts, image scanning and orchestrator-level admission policy.
Avoid these traps
Common mistakes
- Running --privileged to fix an unknown permissions problem.
- Mounting the Docker socket into application containers without understanding host-control implications.
- Assuming an official image automatically meets your organization’s security requirements.
Knowledge check
Can you explain it without looking back?
Open each answer only after you have tried to answer the question yourself.
1Why is --privileged risky?
It grants broad host-facing privileges and defeats many container isolation controls.
2What is the benefit of a read-only root filesystem?
It limits the locations a compromised process can modify; required writable paths can be explicitly mounted.
3Why protect /var/run/docker.sock?
Access to the Docker Engine API can often be used to create highly privileged containers or access host resources.