Hardened Container Images 101: What, Why, and How for DevSecOps [2025]


Transcript:

Most teams use containers, but not all of them know or control how many vulnerabilities or unnecessary packages their base image contains. Hardened container images help to solve these issues. Minimized attack surface, low to zero CVEs, immutable component set, and continuous patching. Let's explore these and other features of hardened container images and see how to integrate them into your workflow.

Many container images ship with some random base that includes a ton of unnecessary tools such as a package manager, a debugger, a compiler, and lots of random utilities. What is worse, the base image often lacks provenance, so it is hard to determine what is in the base image anyway. The result is more than 600 vulnerabilities in a typical container image. Most of them are in the base image, not in the application code.

The attack surface is the size of a given container image. Every scan report contains hundreds of CVEs. You either accept the risk or drown in the attempt to patch them all. Of course, you can try to patch all these vulnerabilities, but few teams do that. And frankly, it is not your job to solve issues in code that you did not write.

Hardened container images are there to solve these issues. One can say that they set a new standard for container image security. The concept of hardened container images rests on four key pillars.

First, a minimalistic base. The image contains only the components your application needs to function in production. No unnecessary packages, hence a reduced attack surface.

Second, low to zero CVEs. The vendor of hardened base images performs continuous patching so the base image stays free of known vulnerabilities.

Third, an immutable component set. Hardened images cannot be modified. There is no package manager and no other ability to change them. The risk of attackers introducing malicious packages or tampering with a container at runtime is minimized.

Fourth, provenance data. The images come with a software bill of materials and a digital signature. You can always verify their origin and the components they contain.

You might have heard of or even used distroless images. What is the difference between them and hardened base images? Distroless images are about stripping down almost all Linux components, including the shell. Image hardening, on the other hand, is about a clear CVE management process: tracking components, monitoring CVEs, and patching them.

Hardened container images integrate perfectly into DevSecOps practices, and here is why. You get reduced noise from security scanners. Fewer CVEs mean fewer false-positive alerts, so the security team can focus on real issues. You can shift security left without slowing down deployments, with hardened images standardized across the organization. Developers do not have to reinvent Dockerfiles every time.

Thanks to SBOMs and digital signatures, hardened container images facilitate compliance and audits. You can say that you know exactly what you are running in production and easily prove it. The potential attack blast radius is reduced. For attackers, it is harder to introduce malicious packages or exploit known vulnerabilities because there is basically nothing in the container image they can leverage.

To sum up, hardened container images are a security baseline. You standardize deployment processes once and solve several problems right away: compliance, CVE monitoring, and patching.

Now let's look at how we can introduce hardened container images into the workflow. There are several vendors who provide hardened container images. I will use BellSoft's hardened images as an example. They are available for free on various registries and for various runtimes.

To try them out, pull the required container image. You can use Cosign to verify the image signature. Then you can run it with your application.

Suppose you have a Dockerfile and you want to migrate to a hardened base. On the screen, you can see a Dockerfile for a Java project. It uses OpenJDK as a base image, compiles, and runs the application. To use a hardened base, we need to rewrite this Dockerfile to use multi-stage builds. We build the application in the first stage and then transfer it into a fresh base image without any packages or tools used during the build. This way, the image will be smaller and free of additional utilities.

If you already use multi-stage builds, migrating to a hardened base image is just a matter of substituting the FROM command. Remember that hardened base images are immutable, so you cannot add additional packages. It is also recommended to pin the image by digest for reproducibility.

As far as signature verification is concerned, Cosign verification can be introduced into the CI/CD pipeline, for example with GitHub Actions.

That was hardened container images 101. Leave a comment if you want me to discuss other topics related to hardened images. And as usual, do not forget to like, subscribe, and until next time.

Summary

Hardened container images address the security risks of traditional container bases by minimizing the attack surface, reducing CVEs, and providing immutable, well-defined components. They rely on continuous patching, strict CVE management, and provenance data such as SBOMs and digital signatures to ensure transparency and trust. Compared to distroless images, hardened images focus not only on minimalism but also on long-term vulnerability tracking and maintenance. They integrate naturally into DevSecOps workflows by reducing scanner noise, simplifying compliance, and standardizing images across teams. Adopting hardened images improves security posture while keeping builds reproducible and deployment workflows efficient.

About Catherine

Java developer passionate about Spring Boot. Writer. Developer Advocate at BellSoft

Social Media

Videos
card image
Mar 9, 2026
jOOQ Deep Dive: CTE, MULTISET, and SQL Pipelines

Some backend developers reach the point where the ORM stops being helpful. Complex joins, nested result graphs, or CTE pipelines quickly push frameworks like Hibernate to their limits. And when that happens, teams often end up writing fragile raw SQL strings or fighting performance issues like the classic N+1 query problem. In this video, we build a healthcare scheduling application NeonCare using jOOQ, Spring Boot 4, and PostgreSQL, and show how to write production-grade SQL directly in Java while keeping full compile-time type safety.

Videos
card image
Feb 27, 2026
Spring Developer Roadmap 2026: What You Need to Know

Spring Boot is powerful. But knowing the framework isn’t the same as understanding backend engineering. In this video, I walk through the roadmap I believe matters for a Spring developer in 2026. We start with data. That means real SQL — CTEs, window functions, normalization trade-offs — and understanding what ACID and BASE actually imply for system guarantees. Spring Data JPA is useful, but you still need to know what happens underneath. Then architecture: microservices vs modular monolith, serverless, CQRS, and when HTTP, gRPC, Kafka, or WebSockets make sense. Not as buzzwords — but as design choices with trade-offs. Security and infrastructure follow: OWASP Top 10, AuthN vs AuthZ, encryption in transit and at rest, Docker, Kubernetes, Infrastructure as Code, and observability with Micrometer, OpenTelemetry, and Grafana. This roadmap isn’t about mastering every tool. It’s about knowing what affects reliability in production.

Further watching

Videos
card image
Apr 2, 2026
Java Memory Options You Need in Production

JVM memory tuning can be tricky. Teams increase -Xmx and assume the problem is solved. Then the app still hits OOM. Because maximum heap size is not the only thing that affects memory footprint. The JVM uses RAM for much more than heap: metaspace, thread stacks, JIT/code cache, direct buffers, and native allocations. That’s why your process can run out of memory while heap still looks “fine”. In this video, we break down how JVM memory actually works and how to control it with a minimal, production-safe set of flags. We cover heap sizing (-Xms, -Xmx), dynamic resizing, direct memory (-XX:MaxDirectMemorySize), and total RAM limits (-XX:MaxRAMPercentage) — especially in containerized environments like Docker and Kubernetes. We also explain GC choices such as G1, ZGC, and Shenandoah, when defaults are enough, and why GC logging (-Xlog:gc*) is mandatory before tuning. Finally, we show how to diagnose failures with heap dumps and OOM hooks. This is not about adding more flags. It’s about understanding what actually consumes memory — and making decisions you can justify in production.

Videos
card image
Mar 26, 2026
Java Developer Roadmap 2026: From Basics to Production

Most Java roadmaps teach tools. This one teaches order — the only thing that actually gets you to production. You don’t need to learn everything. You need to learn the right things, in the right sequence. In this video, we break down a practical Java developer roadmap for 2026 — from syntax and OOP to Spring, databases, testing, and deployment. Structured into 8 levels, it shows how real engineers grow from fundamentals to production-ready systems. We cover what to learn and what to ignore: core Java, collections, streams, build tools, Git, SQL and JDBC before Hibernate, the Spring ecosystem, testing with JUnit, and deployment with Docker and CI/CD. You’ll also understand why most developers get stuck — jumping into frameworks too early, skipping SQL, or treating tools as knowledge. This roadmap gives you a clear path into real-world Java development — with priorities, trade-offs, and production context.

Videos
card image
Mar 19, 2026
TOP-5 Lightweight Linux Distributions for Containers

In this video, we compare five lightweight Linux distributions commonly used as base images: Alpine, Alpaquita, Chiseled Ubuntu, RHEL UBI Micro, and Wolfi. There are no rankings or recommendations — just a structured look at how these distros differ so you can evaluate them in your own context.