Docker container security is the set of controls that stop a containerized workload from becoming an attacker's foothold on the host: scanning images for known vulnerabilities, running processes as a non-root user, dropping Linux capabilities, isolating the container from the host kernel and never handing it the keys to the Docker daemon. This guide is a practical hardening playbook for 2026, focused on the container layer itself rather than the orchestration layer above it.
A Docker container is not a virtual machine. It shares the host kernel, and by default it runs with a surprising amount of privilege. Most real container breaches trace back to a handful of mistakes: a vulnerable base image, a process running as root, a mounted Docker socket or a secret baked into an image layer. Close those gaps and you remove the majority of the practical attack surface.
The Docker container attack surface
Because containers share the host kernel, the isolation boundary is thinner than many teams assume. The relevant attack surface splits into three parts:
- The image: outdated packages, known CVEs, embedded secrets and untrusted base layers.
- The runtime configuration: excessive capabilities, writable filesystems, host bind mounts, privileged mode and the Docker socket.
- The daemon and host: the Docker daemon runs as root by default, so any container that can talk to it effectively controls the host.
Orchestration adds a further layer of risk (RBAC, network policies, admission control) that we cover in our companion guide to Kubernetes pentesting and cluster security. This article stays at the container and image level, which is where hardening has to start.
Docker image scanning: the first line of defense
Docker image scanning is the practice of inspecting each layer of an image against vulnerability databases before it ever reaches production. You want it in two places: the CI pipeline (fail the build on new HIGH or CRITICAL findings) and the registry (rescan continuously, because a base image that was clean last week may carry a fresh CVE today).
Do not treat scanning as a one-off gate. A useful workflow looks like this:
- Scan on every pull request and block the merge on unfixed critical CVEs.
- Generate a Software Bill of Materials (SBOM) in CycloneDX or SPDX format so you can answer "am I affected?" the day the next Log4Shell lands.
- Rescan images already in the registry on a schedule, since vulnerability data changes even when the image does not.
- Enforce a maximum image age so nobody ships a base layer that has not been rebuilt in months.
Docker vulnerability scanner options: Trivy, Grype and Docker Scout
A Docker vulnerability scanner reads the installed packages, language dependencies and OS layers, then matches them against sources like the NVD and GitHub Security Advisories. The mature open source and vendor options are:
- Trivy (Aqua Security): the de facto default. Scans container images, filesystems, Git repositories, IaC and even hardcoded secrets, and runs comfortably inside CI. This is the same class of continuous scanning that a CSPM applies to cloud configuration, only pointed at your images.
- Grype (Anchore): pairs cleanly with Syft for SBOM generation and is easy to script into pipelines.
- Clair (originally CoreOS, now Quay): registry-integrated scanning, a good fit if you already run Quay.
- Docker Scout: native to Docker, surfaces results directly in Docker Desktop and Hub with remediation advice.
Pick one, wire it into CI with a policy that fails the build, and keep the vulnerability feed current. A scanner nobody looks at is just noise.
Trust your base image: the software supply chain
Every FROM line is a supply-chain decision. A bloated base image drags in hundreds of packages you never use, each one a potential CVE. Harden the supply chain with a few disciplined habits:
- Start minimal. Prefer distroless, Alpine or slim variants over full distributions. Fewer binaries means a smaller attack surface and faster scans.
- Pin by digest, not by floating tag.
FROM node:22can change under you;FROM node:22@sha256:...is reproducible and cannot be swapped silently. - Prefer official or verified-publisher images and rebuild your own golden base images on a schedule.
- Verify provenance. Sign images with Cosign and Sigstore, and check signatures at deploy time so an unsigned or tampered image never runs. SLSA provenance attestations close the loop from source to artifact.
The dependency-confusion and poisoned-base-image incidents of recent years all exploited teams that trusted whatever a public registry served. Verification is cheap insurance.
Harden the Dockerfile
Runtime flags matter, but many wins are baked in at build time.
- Set a non-root
USER. By default a container runs as root (UID 0), which maps to a powerful account on the host under classic Docker. Create a dedicated user and switch to it:RUN adduser -D app && USER app. Run as a UID above 0. - Use multi-stage builds to keep compilers, package managers and build secrets out of the final image. Ship only the runtime artifact.
- Prefer
COPYoverADDand add a strict.dockerignoreso you never leak.git,.envor local credentials into a layer. - Never bake secrets into layers. A secret written in one layer and deleted in the next still lives in the image history. Use BuildKit secret mounts (
RUN --mount=type=secret) for build-time credentials. Hardcoded secrets are one of the most dangerous cloud misconfigurations we find in audits, and images are no exception.
Runtime hardening
Drop Linux capabilities
Docker grants a default set of Linux capabilities that most workloads never need, such as CAP_NET_RAW or CAP_SETUID. Drop them all and add back only what is required:
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE myimage
And never reach for --privileged, which disables almost every isolation control at once.
Read-only root filesystem
Run the container with an immutable filesystem so an attacker cannot drop tools or establish persistence:
docker run --read-only --tmpfs /tmp myimage
Mount a small writable tmpfs only where the app genuinely needs scratch space.
Rootless mode
Rootless Docker (and Podman) runs the daemon and containers as an unprivileged user. If a container escape happens, the attacker lands as a normal user rather than as host root, which massively reduces blast radius. There are trade-offs around networking and some storage drivers, but for most application workloads rootless is now production-ready.
seccomp and AppArmor profiles
Docker ships a default seccomp profile that blocks around 40 dangerous syscalls. Keep it on, and tighten it further with a custom profile for high-value workloads. Layer a mandatory access control profile (AppArmor on Debian and Ubuntu, SELinux on RHEL) on top. The one thing never to do is --security-opt seccomp=unconfined, which throws the syscall filter away entirely.
Never mount the Docker socket
Mounting /var/run/docker.sock into a container is equivalent to giving that container root on the host: it can spawn a new privileged container and break out in seconds. CI runners and monitoring agents do this far too often. Safer options include rootless Docker, a hardened runtime like Sysbox, a scoped socket proxy that only exposes the API calls you actually need, or socketless image builders such as Kaniko and Buildah.
Handle secrets outside the image
Secrets belong at runtime, injected by your orchestrator or a vault, never inside the image. Bake them in and they persist in the layer history for anyone who pulls the image. Use BuildKit secret mounts during builds and a secrets manager (HashiCorp Vault, AWS Secrets Manager, the Kubernetes Secrets store) at runtime. This is the same posture discipline that extends up the stack: infrastructure drift is caught by CSPM, SaaS exposure by SSPM and SaaS posture management, and the container is simply the next layer down.
Where container hardening fits
Container hardening is one layer of a broader cloud security posture, not the whole of it. The controls above shut down the common breakout paths, but an external validation still pays off, because a skilled tester chains a weak base image, an over-permissioned mount and a leaked token into an attack path that no single scanner flags. That is exactly what our cloud audit service does: it validates which of your container and cloud findings are genuinely exploitable.
Frequently asked questions
Is Docker container security different from Kubernetes security?
Yes, and the distinction matters. Docker security is about the individual container and its image: capabilities, the user it runs as, the filesystem and the base layers. Kubernetes security adds the orchestration layer on top: RBAC, admission controllers, network policies and secrets management across a cluster. You need both. Harden the container first, then secure how the cluster schedules and connects them.
Which Docker vulnerability scanner should I choose?
For most teams, Trivy is the pragmatic default: it is open source, fast, and scans images, filesystems, IaC and secrets from a single binary. Grype is an excellent alternative, especially paired with Syft for SBOMs. Docker Scout is convenient if you live in Docker Desktop and Hub. The scanner matters less than wiring it into CI with a policy that fails the build on unfixed critical vulnerabilities.
Does rootless mode break existing containers?
Usually not for application workloads. Most containers that run a web service, a worker or an API run fine rootless. You may hit friction with workloads that need low ports, specific storage drivers or host-level networking, but those are the exception. Test in staging, and treat rootless as the default rather than a special case.
How do secrets leak into Docker images?
The classic mistake is copying a .env file or an API key into a layer, or running a build command with a secret as an argument. Even if a later layer deletes the file, the earlier layer still contains it and travels with the image. Use BuildKit secret mounts at build time and inject runtime secrets through your orchestrator or a vault, never through COPY or a plain environment variable baked into the image.
Is image scanning enough on its own?
No. Scanning finds known CVEs in packages, which is essential but partial. It does not fix a container running as root, a mounted Docker socket, an over-broad bind mount or a leaked credential. Scanning is one control among several: combine it with a non-root user, dropped capabilities, a read-only filesystem, seccomp and disciplined secrets handling.
Container security with Secra
At Secra we harden and test containerized workloads end to end: image scanning pipelines, Dockerfile and runtime review, supply-chain verification and orchestration security. If you want an external assessment of your Docker and Kubernetes stack, or help building secure build pipelines, reach out through contact and we will come back with a first evaluation.
About the author
Secra Solutions team
Ethical hackers with OSCP, OSEP, OSWE, CRTO, CRTL and CARTE certifications, 7+ years of experience in offensive cybersecurity, and authors of CVE-2025-40652 and CVE-2023-3512.

