Back to Blog
Containers11 June 2024Michael Hettwer5 min read

The container image hygiene we follow

How we keep container images clean: tags and digests with intent, regular base rebuilds, and vulnerability scanning without permanent noise.

Container images are the unit through which software reaches a server. That is exactly why their hygiene decides two things at once: the risk that enters with every start of an old image, and the speed with which an incident question can be answered, namely what is actually running there. Both trace back to the same root: an image is not a product with a printed expiry date but an artifact that starts aging the moment it is built.

Tags are pointers, not promises

The most common misjudgment is trusting a tag. Tags are renameable pointers: whoever pulls app:latest today may receive a different image than yesterday without the name changing. That is occasionally convenient in development and useless in operations. The workable order reads: builds produce versions with unique tags, and whatever actually gets deployed is referenced as a digest, the checksum of the concrete image. The digest is immutable; it prevents a different content from quietly slipping in under an identical name.

That costs no special tooling landscape, only an agreement: the tag describes what was built, the digest describes what was deployed. Both appear together in the deploy note, and a week later somebody still knows what is running.

Bases age faster than the application

The second issue is sneakier: an own image ages even when its content stays unchanged, because the base underneath it ages. The base libraries the image stands on receive vulnerability fixes, and an image built in January does not carry those fixes in June. The answer is a rebuild habit: base images get pulled regularly and the own images get rebuilt on top of them, even without content changes. The rhythm follows the criticality of the system; a week to a month are the usual spans.

The rebuild only solves its problem if it is checked. A scan of the result belongs in the pipeline: a tool such as Trivy reads the package lists inside the image and reports known vulnerabilities with severity. The useful threshold is not "zero findings", which nobody reaches, but "no new high-severity finding against the last known baseline". Anyone insisting on zero mutes the scanner after two weeks, and the noise eats the signal.

The registry is a warehouse too

The third point concerns where the images live. A registry that accumulates thousands of tags over years is not an archive but a confusion machine: nobody knows anymore which images are outdated, which were never deployed, and which belong to a system long since retired. The remedies are small: a retention rule for old tags, deliberate deletion of orphaned images, and the separation of development and operations so that the build process is the only writer into the production-adjacent areas.

One operational discipline is often underestimated: build environments get no manual login into the registry. Images reach the production-adjacent areas exclusively through the pipeline, and anyone placing something by hand there leaves a trace the next audit notices. That sounds strict but settles in a single permission decision.

The small set we standardize

From our practice, the standard equipment for image hygiene is lean and load-bearing:

  • Deployments reference digests; tags serve naming, not binding.
  • Base images are rebuilt on a fixed rhythm, documented per system class.
  • Every rebuild runs a vulnerability scan, with thresholds that separate genuine new findings from permanent noise.
  • The registry has retention and a cleanup job whose execution is visible in monitoring.
  • Only the pipeline writes into the production-adjacent registry areas.

Why the rule first hits the own base

One experience from the first scan runs belongs up front: the first finding almost never concerns the own application but the base underneath it. The old distribution in the base, the libraries untouched for a year, the cluttered tooling in the build image: the scanner reads first what was shipped along. That is exactly why the rebuild rhythm is the more effective lever, because it renews the substructure without a single line of application code changing.

The second part of the experience concerns the reaction to findings. Not every finding needs an immediate action, but every finding needs a classification: affected or not, fixed with the next rebuild or mitigated by a configuration change. That classification needs a home, and that home is the build note. A week later nobody remembers from memory why a certain finding was accepted; the note turns the scan run into a decision trail that keeps telling its story at the next review.

A sentence about measurement belongs here, because hygiene otherwise becomes a matter of belief: the time from an image's build to its replacement is a number that can be measured and expresses the health of the pipeline better than any instruction. In landscapes where that number drops from months to weeks, the majority of scan findings disappear on their own, because the affected images leave circulation before they are ever deployed. The number belongs in the pipeline's regular review, next to runtimes and error rates, and it is kept there not as a rule but as a hint: when it rises, something in the flow changed, and that is the moment to ask.

The payoff shows not on rollout day but in the first incident where the question "what is actually running there?" gets answered in a minute instead of an afternoon. If you want your image practice on this footing, the containers and Kubernetes page describes the matching service, CI/CD pipeline management the pipeline side, and the contact page is the fastest way to reach us.

Sources

  • Trivy documentation, https://aquasecurity.github.io/trivy/ (accessed 2026-11-03)
  • Open Container Initiative, Image Specification, https://github.com/opencontainers/image-spec (accessed 2026-11-03)
  • Open Container Initiative, Distribution Specification, https://github.com/opencontainers/distribution-spec (accessed 2026-11-03)