Chat with AI Agent, powered by Text

Docker Container Security Best Practices 2023 | Harden & Scan

Docker Container Security Best Practices 2023 | Harden & Scan
Written by
Russ Andersson
Russ Andersson
-
Co-founder & COO, RapidFort
,
Published on
April 3, 2023

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

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

Is Docker secure by default?

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.

How do you secure a Docker image?

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.

Should containers run as root?

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.

What is rootless Docker?

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.

What is the difference between Docker security and Kubernetes security?

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.

How do I check whether a Docker image runs as root?

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.

Subscribe to newsletter

Subscribe to receive the latest blog posts to your inbox every week.

By subscribing you agree to with our Privacy Policy.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Share on:

Latest posts

Ability to Execute

2026 Gartner® Magic Quadrant™

for Software Supply Chain Security

Get the Report