Docker Fundamentals · Module 11 of 12

Container security fundamentals

Reduce attack surface with trusted images, least privilege, non-root processes, capability control, read-only data paths and careful Docker socket handling.

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 1

Default container can write its root filesystem

docker run --rm alpine:3.20 sh -c 'touch /root/demo && echo writable'
STEP 2

Read-only root filesystem blocks the same write

docker run --rm --read-only alpine:3.20 sh -c 'touch /root/demo || echo write-blocked'
STEP 3

Provide 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 4

Drop 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 connection

Production 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.