Docker Advanced: Security, Limits and Production
Container Security and Hardening
In this lesson you will
- Run containers as a non-root user with minimal privileges
- Keep secrets out of images and environment history
- Scan and update images to fix known vulnerabilities
Introduction
Containers isolate processes, but they are not a perfect security boundary. They share the host's kernel. A mistake in your configuration can let an attacker who breaks into one container reach the whole machine. Hardening is about reducing what an attacker can do.
The simple explanation
Give each container the least power it needs, and keep sensitive things out of it.
Do not run as root
By default, processes in a container run as root. Create and switch to an ordinary user in your Dockerfile:
Dockerfile
FROM node:22-slim
WORKDIR /app
COPY --chown=node:node . .
RUN npm ci --omit=dev
USER node
CMD ["node", "server.js"]The official Node image already provides a node user. Other images may need RUN adduser commands. If the app is compromised, the attacker has the powers of an unprivileged user, not root.
Quick quiz
Why run your application as a non-root user inside a container?
Reduce privileges at run time
Terminal
docker run -d \
--read-only \
--cap-drop ALL \
--security-opt no-new-privileges \
--tmpfs /tmp \
my-app:1.4.2--read-onlymakes the container's filesystem read-only, so malware cannot easily write files.--tmpfs /tmpgives a temporary writable folder.--cap-drop ALLremoves Linux capabilities. Add back only what you need with--cap-add.no-new-privilegesstops processes gaining extra privileges.
Never use --privileged or mount the Docker socket (/var/run/docker.sock) into a container unless you fully understand the risk. Either gives near-complete control of the host.
Secrets
- Never put passwords, keys or tokens in the Dockerfile, in
ENV, or in files copied into the image. Anyone with the image can read them, and image layers keep history. - Pass secrets at run time, using a secrets manager, Docker secrets, or your platform's secret store.
- Do not log secrets.
Images and vulnerabilities
- Use trusted, minimal base images, and pin versions or digests.
- Scan images for known vulnerabilities with a scanner such as Docker Scout or Trivy, ideally in your build pipeline.
- Rebuild and redeploy regularly. Security fixes arrive in base images, but your running containers do not update by themselves.
- Remove unused packages and tools from the final image, for example with multi-stage builds.
Network exposure
Publish only the ports you need, bind internal services to 127.0.0.1 or keep them on private networks, and put public services behind a reverse proxy with HTTPS.
A hardening checklist
- Non-root user
- Minimal base image, pinned
- No secrets in the image
- Read-only filesystem where possible, and dropped capabilities
- Scanned in CI, and rebuilt regularly
- Only necessary ports published
- Resource limits set (next lesson)
Try it yourself
Take one of your Dockerfiles and add a non-root USER. Run it with --read-only --cap-drop ALL and note what breaks, then add back only what the app truly needs.
Summary
- Containers share the host kernel, so reduce privileges: non-root, read-only, dropped capabilities.
- Keep secrets out of images, and never mount the Docker socket or run privileged without a strong reason.
- Scan and rebuild images regularly, and expose only the ports you need.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.
Sources and further reading