Docker Container Security Best Practices 2023 | Harden & Scan

In brief
- The base image is the first Docker security control to get right, because every image inherits the contents of its base.
- Twelve practices cover the image (secure base, digest pinning and signatures, minimal contents, non-root, read-only filesystem, no secrets in layers), the runtime (ports, resource limits, a hardened daemon or rootless mode) and the pipeline (scan and gate, rebuild on fixes, enforce at admission).
- Docker's own documentation, the OWASP Docker Security Cheat Sheet, the CIS Docker Benchmark, NIST SP 800-190 and the Kubernetes documentation are the main references behind the practices.
Docker security is the set of practices that keep Docker images, running containers and the Docker daemon safe. The first practice is the base image you start from, because every image inherits the contents of its base. The twelve practices below run from image to runtime to pipeline, with the primary source for each, and together they cover how to keep images patched, how to stop containers running with more privilege than they need, and how to gate builds without drowning in scanner noise.
Why Docker security differs from host security
A container shares the host kernel and is created from an image that someone else largely built. On a host you patch one operating system; in Docker you have an image per service, each carrying its own operating system packages, and every image inherits the contents of its base image, so any vulnerable packages in the base ship in every image built on it. Docker's own engine security documentation covers the daemon attack surface, kernel namespaces and capabilities, and the OWASP Docker Security Cheat Sheet is the practitioner reference for container configuration.
Twelve Docker security best practices
1. Start from a secure or near-zero CVE base image
Pick a maintained base on the distribution your application is tested on, with few or no known vulnerabilities and a published patch window for new ones. Docker calls choosing the right base image the first step towards achieving a secure image, and a base with fewer known vulnerabilities reduces the inherited share of risk before any later practice applies. What are secure base images?, What is a near-zero CVE image?
2. Pin images by digest and verify signatures
Reference base images by digest, not by a mutable tag like latest, so a rebuild cannot change what you ship without your knowledge. Verify signatures at build and at deployment; Sigstore records signatures in a tamper-resistant public log, and Cosign signs container images.
3. Keep images minimal
Include only what the application runs. Use multi-stage builds so compilers and build tools stay out of the final image, and prefer a distroless variant where the service needs no shell or package manager. How to harden a container image?
4. Run as a non-root user and drop capabilities
Set USER in the Dockerfile, and at run time drop all capabilities, adding back only those the process needs. Docker's engine security documentation calls removing all capabilities except those explicitly required the best practice, and OWASP calls an unprivileged user the best way to prevent privilege escalation attacks.
5. Use read-only filesystems and tmpfs
Run containers with a read-only root filesystem and mount a tmpfs for scratch space. NIST SP 800-190 recommends read-only root filesystems because they isolate writes, and any tampering, to specific locations that are easier to monitor.
Practices 4 and 5 at run time:
docker run --read-only --tmpfs /tmp --cap-drop=ALL --user 10001:10001 \ registry.example.internal/approved/app:1.4.2@sha256:<digest>
6. Keep secrets out of images and layers
Never copy credentials into an image or set them in a Dockerfile ENV or build argument; they persist in the final image, where anyone with the image can read them. Inject secrets at runtime from a secrets manager.
7. Limit network exposure
Publish only the ports the service needs and avoid binding to all interfaces, which is the default. On a single host, confirm how Docker's published ports interact with the host firewall; in Kubernetes, use network policy between workloads.
8. Set resource limits
Set memory and CPU limits so a compromised or misbehaving container cannot exhaust the host and take neighbors down with it. By default, a container has no resource constraints.
9. Scan on every build and gate on policy
Scan each build and fail the pipeline on findings that violate your policy. Read results for what applies: in a study of 927 Docker images, Trivy and Grype reported conflicting results for the 865 images that had vulnerabilities (IEEE SCAM 2024). Gate on severity plus the CISA Known Exploited Vulnerabilities catalog, and give every exception an expiry date. You could also prioritize your CVE backlog using the BOD 26-04 criteria.
10. Rebuild when upstream fixes land, on a stated cadence
A build that passed scanning last month can carry CVEs disclosed since then. Rebuild when a security fix is available for a package in the image, not only when the application changes, update the pinned base digest when you rebuild, and know the patch window of whoever maintains your base.
11. Harden the daemon and prefer rootless mode
Protect the Docker socket, since access to it is equivalent to root access to the host. Enable user namespace remapping, which leaves the daemon running as root, or run Docker in rootless mode, which runs both the daemon and containers without root privileges, where the workload allows. Follow the CIS Docker Benchmark for daemon and host configuration.
12. Enforce policy at admission in Kubernetes
Make the practices above non-optional. Kubernetes admission controllers intercept requests before a resource is saved, and Kyverno or OPA Gatekeeper can reject images from unapproved registries and pods that do not require a non-root user. Kyverno verifyImages rules check image signatures; Gatekeeper does so only through external data providers, a beta feature.
Common Docker security issues these practices prevent
- Inherited CVEs from an unmaintained base (practices 1. Start from a secure or near-zero CVE base image and 10. Rebuild when upstream fixes land, on a stated cadence).
- Supply chain substitution through a mutable tag (2. Pin images by digest and verify signatures).
- Oversized images with shells and compilers an attacker can use (3. Keep images minimal).
- Container escape with root privileges (4. Run as a non-root user and drop capabilities, 11. Harden the daemon and prefer rootless mode).
- Tampering with binaries and configuration inside a running container (5. Use read-only filesystems and tmpfs).
- Leaked credentials in image layers (6. Keep secrets out of images and layers).
- Lateral movement through exposed ports (7. Limit network exposure).
- Denial of service from a runaway container (8. Set resource limits).
- Shipping known-vulnerable images because the pipeline did not check (9. Scan on every build and gate on policy), and,
- Configuration drift across teams because nothing enforced the standard (12. Enforce policy at admission in Kubernetes).
How to implement Docker security in CI/CD
Put the checks in the pipeline so they run on every build. Build from the approved base, scan, generate the SBOM, push to the controlled registry, and sign by digest; fail the build on policy violations; let admission control reject anything that bypasses the pipeline. Keep the exception list short and time-boxed, and review it weekly. The pipeline is also where scanner noise is handled: separating findings in packages that never execute from findings in code that runs is what keeps the gate credible.
Docker security tools: what each category does
Four categories of tools support these practices. Image scanners and SBOM generators show what is in an image and which known vulnerabilities it carries. Signing and provenance tools prove where an image came from and that it has not changed. Policy engines at admission enforce the rules. Runtime security tools detect anomalies in running containers, such as unexpected processes, changes to protected files and binaries, and unexpected network activity, which NIST SP 800-190 recommends as container-aware tooling. A fifth category, vendor-maintained near-zero CVE base images, removes risk before the other four see it.
How RapidFort fits
RapidFort Images cover practice 1: drop-in base images on Ubuntu, Debian, Red Hat and Alpine, pin-for-pin compatible with no re-baselining, manually patched and rebuilt by RapidFort engineers, with up to 99.9% CVE elimination across distroless and full images. Swap the image tag in your build and deploy with your existing pipelines. For practice 9, RapidFort Analyzer enumerates all files, packages and configurations within container images, not just those reported by package managers, confirms whether a vulnerability truly applies to the image by accounting for distribution specifics, package presence and configuration context, and exports SBOMs in SPDX, CycloneDX, JSON and CSV; teams can incorporate the RapidFort CLI into their CI/CD pipelines. For practice 3, RapidFort Optimizer uses RBOM® runtime intelligence to identify components that never execute and safely remove them while preserving application functionality.
Frequently asked questions
Docker isolates containers with kernel namespaces and control groups, and by default it drops all capabilities except those needed and applies default seccomp and AppArmor profiles, so Docker describes containers as quite secure by default, especially when processes run as non-privileged users. Two defaults still need attention: containers run as root unless you set a user, and the daemon requires root privileges unless you use rootless mode.
Start from a secure base, include only what runs, set a non-root user, keep secrets out, pin by digest, sign it, scan it on every build and rebuild when fixes land.
No. Set a dedicated user in the Dockerfile and enforce it with the orchestrator. Root inside a container has fewer privileges than root on the host because Docker drops all capabilities except those needed, and user namespace remapping or rootless mode maps it to an unprivileged host user, which helps mitigate the risk of container breakout.
Rootless Docker is a mode that runs the Docker daemon and containers as a non-root user inside a user namespace, to mitigate potential vulnerabilities in the daemon and the container runtime; the shared kernel remains part of the security boundary. Docker documents known limitations, including supported storage drivers, resource limits only with cgroup v2 and systemd, and no AppArmor, checkpoint or overlay networks. Use it where the workload allows.
Docker security covers the image, the container and the daemon on a host. Kubernetes security adds the orchestrator: access control, admission policy, security contexts, network policy and secrets across a cluster. The image practices carry over unchanged; Kubernetes is where they are enforced.
Run docker image inspect and check the User field. An empty value means the container runs as root (UID 0) unless a user is set at start, and a value of 0 or root also means root. In Kubernetes, runAsNonRoot: true makes the kubelet refuse to start a container that would run as UID 0, and the Pod Security Admission restricted level requires that setting at pod creation, making the check a policy.
Latest posts
Eliminate Attack Vectors at the Source
Continuously eliminate up to 99.9% of CVEs without code changes
Products
Use Case
Quicklinks
Stay in touch
Subscribe for product updates and RapidFort newsletter.
Address
440 North Wolfe Road, Sunnyvale, CA 94085
© 2026 RapidFort, Inc.
RapidFort, RAPIDFORT, and RBOM® are registered trademarks of RapidFort, Inc. All other marks and names mentioned herein may be trademarks of their respective companies.







