Distributed Systems & Enterprise ResiliencePlaybook3 min readUpdated September 2026

Hardening Containers Without Slowing Down Builds

Container hardening has a reputation for slowing teams down, mostly because it's often bolted on late, as a pile of new scanner findings dumped on a team right before a launch. Done earlier and as a short, repeatable checklist instead, it barely touches build time at all.

This is that checklist: the handful of things that actually reduce risk, in the order that causes the least friction, plus the mistakes that quietly undo the hardening work after it's done.

Vendors Covered in this Article

Disclosure: We may earn a commission if you buy through some links on this page. It doesn't change what we recommend.

Why start container hardening with a minimal base image?

Every package in your base image is something that can have a vulnerability, whether or not your application ever uses it. A minimal or distroless base image, containing only what your application actually needs to run, shrinks that surface before you've written a single hardening rule.

This is also the cheapest step to adopt, since it's usually a one-line change to your Dockerfile's base image, not a new process the team has to learn.

Run as a Non-Root User by Default

A container running as root, combined with a container escape vulnerability, hands an attacker root on the host. Set a non-root user in the image itself rather than relying on runtime configuration to catch it, since a forgotten runtime flag is a common way this protection quietly disappears.

Test that your application actually works as a non-root user before rolling this out broadly, since file permission issues from a root-only default are the most common reason teams roll this back.

Roll it out service by service rather than across every image in one change. A permission failure in one low-traffic internal service is a quick fix; the same failure discovered simultaneously across every production service at once is an incident.

Patch Cadence Matters More Than a Clean Scan Today

A clean scan result today says nothing about next week, when a new CVE gets disclosed against a package sitting in an image nobody's rebuilt. Federal guidance treats a critical, internet-facing vulnerability as needing remediation within 15 days, and a known exploited one within as little as 14, and that clock starts the moment the CVE is public, not whenever your team next happens to rebuild the image1.

A scheduled rebuild cadence, even something as simple as a weekly base image refresh, catches most of this automatically, without anyone having to notice the new CVE first.

Why scan the built image, not just the Dockerfile?

A Dockerfile that looks clean can still produce a vulnerable image, because the vulnerabilities live in the packages that get installed, not in the instructions that install them. Scan the built image itself, ideally in CI before it ever reaches a registry, so a vulnerable image never gets the chance to be deployed in the first place.

Set the scan to fail the build on critical findings, not just report them. A scan result nobody's required to act on tends to get ignored the same way any unenforced warning does.

The Mistake: Hardening the Image and Ignoring the Runtime

A hardened image can still run with a permissive runtime configuration: mounted host directories it doesn't need, capabilities it never uses, network access wider than necessary. Runtime configuration is a separate control surface from the image itself, and hardening one without the other leaves half the job undone.

Review runtime configuration with the same checklist mindset as the image build: least privilege by default, with any broader access requiring a specific, documented reason rather than being the default nobody questioned.

This split is exactly why a clean scan result can create false confidence. A scanner checking the image tells you nothing about how permissively that image is actually being run in production, which is why both checklists need to exist side by side, not as a single combined pass.

A short written checklist for each, reviewed whenever a new service is added, does more for actual security over time than a longer list nobody consistently applies to every service.

Run this short checklist on every image:

  1. Start from a minimal or distroless base image that contains only what the application needs to run.
  2. Set a non-root user in the image itself, and test that the application works as that user.
  3. Rebuild images on a regular schedule, weekly is a reasonable start, so newly disclosed vulnerabilities get caught.
  4. Scan the built image in CI, and fail the build on critical findings before it reaches a registry.
  5. Review runtime configuration for unneeded mounted host directories, unused capabilities, and network access wider than necessary.
Executive Capability Standard

What Good Looks Like

Good container hardening means a minimal base image, a non-root runtime user, and an image scan that fails the build on critical findings, backed by a scheduled rebuild cadence so newly disclosed vulnerabilities don't sit unpatched indefinitely.

Building The Capability (5-Stage Skill Ladder)

1. Learn:Read your container runtime's documentation on non-root users and capability restrictions, since most teams are running with more default privilege than their application actually needs.
2. Do Manually:Switch your base images to minimal or distroless variants and set a non-root user in the Dockerfile, testing each service individually as you go.
3. Delegate:Give a specific engineer ownership of the image scanning pipeline and the scheduled rebuild cadence, so newly disclosed vulnerabilities get caught on a schedule instead of by chance.
4. Automate:Wire image scanning into CI with a hard fail on critical findings, and automate a weekly base image rebuild so patched packages flow through without anyone having to remember to trigger it.
5. Buy:Bring in a container or cloud workload security platform once you have enough services and images that manual scanning and rebuild tracking can't keep pace.

How to Get Started

Disclosure: We may earn a commission if you buy through some links on this page. It doesn't change what we recommend.

Frequently Asked Questions

Does container hardening have to slow down our build pipeline?

Not if it's built in as a short, repeatable checklist from the start rather than added as a pile of scanner findings right before launch. A minimal base image, a non-root default, and an image scan in CI add very little build time and catch most of the real risk.

Is scanning our Dockerfile enough, or do we need to scan the built image?

Scan the built image. Vulnerabilities live in the packages that actually get installed, not in the Dockerfile instructions themselves, so a clean-looking Dockerfile can still produce a vulnerable image. Scanning in CI before the image reaches a registry catches this before it's ever deployed.

How often should we rebuild our container images even if nothing changed?

On a regular schedule, weekly is a reasonable starting point for most teams, rather than only when your own code changes. New vulnerabilities get disclosed against existing packages constantly, and a scheduled rebuild catches those automatically instead of relying on someone noticing a new CVE.

Do we still need to check runtime configuration after hardening our container images?

Yes. A hardened image can still run with a permissive runtime setup, unnecessary mounted directories, excess capabilities, wider network access than needed, which undoes much of the benefit. Treat runtime configuration as its own checklist, applying least privilege by default the same way you did for the image.

Sources

Where we quote a benchmark, we show its source. Other figures in this guide are estimates or general guidance, so check them against your own numbers.

  1. Security patch remediation SLAs (CISA federal mandates, used as industry norm). CISA Binding Operational Directives 19-02 and 22-01 (CISA briefing hosted at NIST CSRC), 2022.

Related Guides