API Security, Identity & Zero-TrustPlaybook3 min readUpdated September 2026

Hardening Containers Without Slowing Every Deploy

Container hardening advice tends to arrive as an enormous checklist that treats every recommendation as equally urgent. In practice, a handful of changes catch most of the real risk, and the rest are worth doing once you've got those in place rather than before. Here's the hardening work roughly ordered by how much protection it buys against how much friction it adds to your deploy pipeline.

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 should you start from a minimal base image?

A base image built for general use ships a shell, package managers, and utilities you'll never call at runtime, all of which are also tools an attacker can use if they get a foothold inside a running container. Switching to a minimal or distroless base image removes most of that surface in one change, and it's usually a smaller lift than teams expect: the build stage can still use a full image to compile, while only the minimal image needs to ship in the final layer. Start with your highest traffic or most internet exposed service rather than trying to convert the whole fleet in one pass, so you can confirm nothing in your runtime actually depended on a shell being present before rolling the change out further.

For example, a team converting its most internet exposed service to a minimal image may find that a startup script quietly relied on a shell. Catching that in one service is a small fix, while discovering it across the whole fleet is an outage. The same applies to the non-root setting: apply it to one service, confirm the process can still write where it needs to, then extend it. A common mistake is changing every image in one pass to finish faster, which spreads a single missed dependency across every service at once.

Run as a non-root user by default

A container that runs as root doesn't need a second vulnerability to do serious damage: if the application process itself is compromised, it already has root inside the container and a shorter path to escalating outside it. Setting a non-root user in your Dockerfile and confirming your orchestrator enforces it, rather than allowing an override, is a small config change with an outsized effect on what a compromise can actually reach.

When should you scan container images for vulnerabilities?

Vulnerability scanning is far more useful in the build pipeline than as an after the fact audit of a fleet already in production, because a failed scan can block a bad image from shipping in the first place. Continuous scanning platforms like Tenable check your base images and installed packages against known vulnerability databases and flag what's exploitable, which matters more for prioritization than a raw vulnerability count: a container with fifty low severity findings and no network exposure is a lower priority than one with a single known exploited vulnerability sitting on an internet facing service.

Treat the runtime, not just the image, as something to watch

A clean image at build time doesn't guarantee a clean container at runtime, since a compromised application can still spawn an unexpected process or open a connection nothing in the original image predicted. Runtime protection tools such as CrowdStrike watch for that kind of behavioral anomaly inside a running container fleet, which catches a category of attack that image scanning alone misses entirely: one that only shows up after the container is already serving traffic.

Pin and rebuild on a schedule, not only when something breaks

Floating base image tags quietly drift as the upstream image changes underneath you, which means a container you haven't touched in months can pick up a new vulnerability on its next rebuild without any code change of your own. Pin to a specific digest for reproducibility, but pair that with a scheduled rebuild, weekly is reasonable for most small teams, so pinned images don't silently fall behind on patches while staying technically unchanged. A calendar reminder is a fine way to start this habit before you invest in automating it.

Network policy is part of hardening, not a separate project

A hardened container that can still reach every other service on the network by default hasn't actually shrunk the blast radius of a compromise. Default deny network policies between containers, opening only the specific connections a service actually needs, mean that even a successfully compromised container can't freely move laterally to something more valuable. This is usually cheaper to set up early, while your service graph is small, than to retrofit once dozens of services all assume open network access to each other.

Hardening steps, ordered from most protection per unit of friction:

  1. Move to a minimal or distroless base image, starting with your most internet exposed service.
  2. Set a non-root user in the Dockerfile and confirm your orchestrator enforces it.
  3. Scan images in the build pipeline so a failed scan can block a bad image from shipping.
  4. Pin base images to a digest and rebuild on a schedule, such as weekly, so patches are not missed.
  5. Add default deny network policies and open only the connections each service needs.
  6. Add runtime protection that watches for unexpected behavior in running containers.
Executive Capability Standard

What Good Looks Like

A hardened container runs a minimal image as a non-root user, gets scanned before it ships, and can't reach services it has no reason to talk to by default.

Building The Capability (5-Stage Skill Ladder)

1. Learn:Audit your current base images and Dockerfiles for root users, unnecessary installed packages, and floating tags.
2. Do Manually:Switch your highest traffic services to minimal base images and non-root users, and confirm the change in a staging deploy before production.
3. Delegate:Assign an engineer to own a scheduled rebuild cadence for pinned images and a default deny network policy between services.
4. Automate:Add image scanning as a required CI gate so a build with a known exploited vulnerability can't ship without an explicit override.
5. Buy:Bring in outside container security expertise if you're hardening a fleet that's been running unmanaged for a long time and want a prioritized starting list.

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

What's the single highest impact container hardening change for a small team?

Switching to a minimal base image and running as a non-root user, since both are one-time config changes that meaningfully shrink what an attacker can do with a compromised container, without adding ongoing operational work.

Do we need runtime protection if we already scan images before deploy?

Image scanning and runtime protection catch different things: scanning finds known vulnerabilities before deploy, while runtime tools catch unexpected behavior in a container that was clean at build time but gets compromised after it's serving traffic. Small teams often start with scanning alone and add runtime protection once they have production traffic worth protecting.

How often should we rebuild containers that use pinned image digests?

Weekly is a reasonable default for most small teams, often tied to your normal deploy cadence rather than a separate process. The goal is catching upstream patches promptly even though the pinned digest itself doesn't change on its own.

About the numbers

This guide doesn't quote a sourced benchmark. Figures in it are estimates or general guidance, so check them against your own numbers.

Related Guides