Container images are the foundation of modern application delivery, but many teams build containers that contain far more software than their application needs. This is because a typical base image may include package manager, download utilities, debugging tools, libraries, and operating-system components not required in production. The problem is that each unnecessary component increases the attack surface and makes security scanning harder to manage.
Hardened container images are designed to change that as they provide a minimal, security-focused foundation for running applications.
This article explains what hardened container images are, how they differ from standard images, and where they fit into a modern container security strategy.
It also uses BellSoft Hardened Images as an example of how organizations can build and run Java and other workloads on a smaller, signed, traceable, and continuously maintained container base.
Why Traditional Container Images Create Security Risks
Container images make cloud deployment fast and portable, but ironically, the most convenient part of the software supply chain is often also the weakest one. The Netrise Supply Chain Visibility & Risk Study has revealed that an average container image comes with 604 known vulnerabilities, almost half of them years old.
This isn’t because the engineers are doing their job badly at eliminating the CVEs. This is because container images contain many layers such as OS packages, possibly a language runtime, system libraries, configuration files. Many of the components in these layers are not required by the application running in production, but nevertheless, each layer adds to the attack surface with unpatched packages, unmaintained dependencies, untrusted base images, or misconfigurations. Even worse, new vulnerabilities are discovered constantly, and what was safe yesterday becomes flawed today. As a result, teams spend a lot of engineering resources on constant firefighting in the code they didn’t even write.
Some container image components might not contain known CVEs, but introduce security risks by themselves. For instance, a package manager can give the attacker an opportunity to install malicious packages.
Hardened images are aimed to solve these issues at the very foundation — the base image.
What Are Hardened Images?
Hardened images are minimized, immutable container images that contain only essential components for running an application and are continuously patched and shipped with provenance metadata to reduce known vulnerabilities and supply-chain risks.
Minimized attack surface is not their only characteristic, albeit a very important one. Here are five factors that differentiate hardened images from standard base images:
- Minimalism: The hardened base image contains only the components the application requires to run, no spare parts.
- Immutable component set: There is no package manager or download utilities, so the images cannot be changed externally.
- Continuous patching: The hardened images have low-to-zero CVEs by design, and the maintainer continuously updates the images with the latest batches to keep the images clean.
- Built-in provenance data: The hardened images come with provenance data such as a Software Bill of Materials (SBOM) and a cryptographic signature verifying that the software artifact wasn’t altered.
- Vendor accountability: The vendor owns the base images as a product, offering a commitment to constant patching, a defined release cadence, and response SLAs when critical issues emerge.
|
Area |
Standard container images |
Hardened container images |
|
Component set |
Often broad |
Minimal, purpose-built |
|
Package manager, shell, and download utilities |
Commonly included |
Typically removed |
|
Attack surface |
Larger |
Reduced |
|
Known CVEs |
Depends on the vendor; for images with unclear maintenance strategy, can accumulate quickly |
Continuously monitored and remediated |
|
Provenance |
May be limited |
SBOMs and signed artifacts |
|
Image contents |
Vary by tag and vendor |
Controlled and documented |
|
Runtime changes |
Packages may be added |
Immutable component set |
|
CI/CD verification |
Optional |
Designed for policy checks |
|
Debugging |
Tools often included |
Separate debug workflow needed |
|
Supply-chain controls |
Usually external |
Built in through signatures and metadata |
|
Compliance |
Usually not compliant with regulatory requirements |
Configured to meet various regulatory requirements (FIPS, STIG, etc.) |
Given their innate characteristics, hardened images can help teams break the vicious circle of CVE firefighting, stop wasting engineering resources on patching the third-party code such as OS or runtime, and build their infrastructure on a secure and compliant foundation.
Hardened images vs slim, distroless, and scratch
Before hardened images, there were slim, distroless, and scratch images. How do hardened images differ from them? And how do they differ from each other while we are at it?
Container image labels can be confusing. Terms such as slim, distroless, and scratch mainly describe what is included in an image. They do not, by themselves, explain who maintains the image, how quickly it is patched, or whether teams can verify its contents.
Scratch is an empty base image. It has no Linux distribution, shell, shared libraries, certificates, or package manager. To use it, you add the application binary and every file it needs yourself. Scratch works well for statically linked Go or Rust binaries. It is usually impractical for Java applications because a JVM needs a runtime and supporting libraries.
Distroless images contain the runtime files an application needs. The most minimalistic distroless image contains only ca-certificates, timezone data, /etc/passwd file, and a tmp directory. Some distroless images may contain a libc implementation and selected shared libraries. But all of them exclude a shell and package manager.
Slim images are reduced versions of conventional Linux-based images. They remove some packages including the package manager and sometimes a shell, but their exact contents vary by vendor and tag.
Hardened images describe a different dimension. Although a hardened image can also be distroless, its definition goes beyond the number of files removed from the final layer. It should have a deliberately limited and immutable component set, documented provenance, signed artifacts, an SBOM, a vulnerability-management process, and a defined update policy.
That distinction matters because a small image can still contain outdated packages, come from an unclear source, or leave teams without a predictable path for security fixes. Hardened images address those operational questions as well as image size.
Benefits of Hardened Images
Hardened images give teams a more controlled starting point for container security by reducing avoidable risk and facilitating compliance.
Smaller attack surface
Removing tools such as wget, package manager, compiler, and debugger limits what an attacker can do. Without those tools, it is harder to inspect the environment, install software, or fetch additional payloads.
Less scanner noise
Smaller images contain fewer packages and utilities, so they usually generate fewer CVE findings. That helps development and security teams focus on issues that affect the application instead of triaging vulnerabilities in components not used by any service.
Predictable patching cadence
A hardened-image vendor maintains the components included in its images and publishes updates when vulnerabilities are found. Instead of reactively patching operating-system packages and runtime dependencies one by one, teams can move to an approved base image with a documented release schedule and remediation SLA.
Clear supply-chain controls
SBOMs, image signatures, and provenance metadata show where an image came from, what it contains, and whether it has changed. Teams can use that information to enforce CI/CD policies and demonstrate that production workloads run approved artifacts.
Facilitated compliance work
Many regulations, for example, EU Cybersecurity Act or the U.S. President’s Executive Order No. 14028 on Improving the Nation’s Cybersecurity, require an accurate software inventory, vulnerability management, and oversight of third-party dependencies. Hardened images simplify that work directly by providing the required compliance data and indirectly by reducing the number of included components and making image contents easier to document and review.
Consistent secure defaults
Platform teams can standardize on a set of hardened base images for projects instead of leaving every team to choose public images or build Dockerfiles from scratch. This reduces variation between services and makes security practices easier to apply across the organization.
It is important to understand that hardened images do not magically solve all issues with enterprise container security. You still need to implement reasonable security measures such as not running privileged containers or giving them excessive capabilities. Nor do hardened images magically rebuild, re-test, and redeploy your services when a patch becomes available.
But what they really do is give teams a smaller, traceable, and easier-to-maintain foundation, leaving more attention for the application code and infrastructure they are responsible for.
What Are BellSoft Hardened Images?
Several vendors provide hardened container images built around similar principles: reduce unnecessary components, track known vulnerabilities, publish software metadata, and rebuild images when security fixes become available.
BellSoft Hardened Images follow this model as well, offering images for Java, GraalVM Native Image, Python, Go, C/C++, and Node.js. Each image includes an SBOM and is cryptographically signed, allowing teams to inspect image contents, verify artifact integrity, and enforce provenance checks in CI/CD pipelines.
Some distinctive features of BellSoft Hardened Images include:
- “3-in-1” approach to security. The images are designed around a stack that BellSoft maintains themselves across the operating system, language runtime, and container image layers. It means that one team covers the OS, runtime, and container security under one SLA and can proactively create patches for known CVEs without having to wait when the patch appears upstream. This allows the teams to standardize on a chosen set of images without having to manage several vendors.
- Focus on compatibility. The images are based on Alpaquita Linux, a lightweight Linux distribution designed for cloud and container workloads and available with either musl or glibc, with AMD64 and ARM64 support. This gives teams a smooth migration path for existing workloads without requiring them to rework the application to adopt a new base image.
- Multiple delivery channels. The images are available on Docker Hub, GitHub Container Registry, Microsoft Container Registry, Google Container Registry, and Amazon ECR for seamless integration into the existing infrastructure.
- Flexible plans. BellSoft Hardened Images are open source and free to use in production. Commercial plans add remediation commitments, including a seven-day SLA for critical CVEs and a 14-day SLA for high, medium, and low severity vulnerabilities.
Getting Started with Hardened Images
In many cases, migration to hardened images should be issue-free. The work is in checking the assumptions that the old image supported and developers relied on.
The image intentionally omits tools that developers often assume are available: package manager, download utilities, and debugging commands. Distroless BellSoft hardened images also don’t contain a shell. It means that any step that relies on these components, such as downloading a file at startup or installing a package inside a running container, belongs in the build process or in a separate operational workflow.
Step 1: Select a hardened image
Start with one service that has a simple runtime profile. Choose the hardened images for your language and the libc variant, musl or glibc.
For Java applications, a musl-based image is smaller and works well for many self-contained services. A glibc-based image is often the safer choice when the application depends on JNI, Java agents, native libraries, or third-party binaries built against glibc.
Step 2: Change the Dockerfile
A basic migration may look like this.
Here’s a Dockerfile for creating a Java container image on a general-purpose base:
FROM eclipse-temurin:25-jdk as builder
WORKDIR /app
COPY . /app/app
RUN cd app && ./mvnw package
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app/app/target/*.jar"]
Update the base image in the Dockerfile. You can keep it as single-stage, but it is strongly recommended to use Docker multi-stage builds to keep the final image as clean as possible.
FROM bellsoft/hardened-liberica-runtime-container:jdk-25-musl as builder
WORKDIR /app
COPY . /app/app
RUN cd app && ./mvnw package
FROM bellsoft/hardened-liberica-runtime-container:jre-25-nonroot-musl
WORKDIR /app
COPY /app/app/target/app-*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app/app.jar"]
The base image used for the second stage includes a nonroot tag, which means that the container will run as nonroot, so you don’t have to specify the non-root user manually.
Step 3: Build the image and test it
Build the image with the hardened base, run it locally, and use the same tests and deployment checks as for a normal release.
The application code and startup command stay the same. The main change is the runtime base: a minimized, immutable image with fewer components to scan and maintain.
In case you are used to having diagnostics tools for debugging, use a separate ephemeral troubleshooting container. The same goes for profiling.
Step 4: Verify the signature and retrieve an SBOM
Hardened images come with a cryptographic signature and an SBOM, so in the production pipeline you should verify the signature and attestations before building a container image to make sure that this is exactly the image you have chosen.
You can use an open source tool Cosign to verify the image and retrieve an SBOM in one go. Download and save the BellSoft public key and use the following command:
$ IMG='docker.io/bellsoft/hardened-liberica-runtime-container:jre-25-nonroot-musl'
cosign verify-attestation \
--key ~/keys/cosign-bellsoft.pub \
--type cyclonedx \
$IMG | jq -r '.payload' | base64 -d | jq '.predicate'
Where ~/keys/cosign-bellsoft.pub is the path to the public key provided by BellSoft and --type is the type of SBOM (both spdxjson and cyclonedx are supported). This command should print out the SBOM content to the standard output.
Hardened Images Adoption Checklist
A hardened image works best when the build and delivery process is prepared for it. Replacing the FROM line is usually easy. Discovering that an old startup script relies on curl, bash, and a package manager is bound to introduce some friction at the start. Also, an update strategy is still needed because if the vendor updates the image with the latest patches, and you rebuild the services once a year, the low-to-zero CVE promise will not hold out for long.
Therefore, use this checklist when moving services to hardened base images.
|
Action item |
Clarification |
|
List runtime dependencies |
Check for native libraries, Java agents, shell scripts, and external binaries. Anything the application needs at runtime must be present in the final image. |
|
Remove package installation at startup |
Do not install utilities or dependencies when the container starts. Add required files during the build, or create a derived image when a dependency belongs in production. |
|
Choose the libc variant |
Use musl when the application has no compatibility issues and the tests show improved performance. Use glibc when the workload depends on native components built for glibc, or when testing shows that it is the safer option. |
|
Use multi-stage builds |
Use a multi-stage Docker build and copy only the final JAR, binary, or static assets into the hardened runtime image. |
|
Run a non-root user |
Use a non-root base image or set an explicit user in the Dockerfile. Verify that the application can write only to the directories it needs, such as a temporary-data or log directory. |
|
Configure the ports |
Run the application on a non-privileged port, such as 1025 or above. In Kubernetes and Docker Engine releases before 20.10, a non-root process cannot bind to ports below 1024 inside the container. |
|
Pin image digests |
Use digests in production deployments instead of tags. A digest identifies the exact artifact that passed testing; a tag can later point to a different one. |
|
Decide how debugging will work |
Keep diagnostic tools out of the production image. Use a dedicated debug image, an ephemeral container, or cluster-level observability tools when troubleshooting is required. |
|
Verify images in CI/CD |
Check signatures, inspect and retrieve SBOMs, and apply policy checks before deployment. This confirms that the image came from an approved source and contains the components you expect. |
|
Assign ownership for base-image updates |
Decide who monitors hardened image releases, tests updated images, and approves rollout. A remediation SLA only helps when you rebuild and deploy the patched image. |
Conclusion
Hardened images are not a substitute for secure code, runtime controls, or vulnerability management. But they work at the foundation, removing unnecessary software from the base layer and making the remaining components easier to verify, patch, and maintain.
BellSoft Hardened Images give Java and other production workloads a maintained base with signed artifacts, SBOMs, and musl or glibc variants. BellSoft maintains both the Linux layer and the runtime, so teams are not left stitching together updates from separate vendors when a vulnerability lands.
The sensible way to evaluate them is to start with one service. Run it through the existing build and deployment pipeline, then compare the image contents, scanner output, and debugging experience with the current base image. If you have any questions regarding the hardened images, including the migration and customization, our engineers will be happy to help.







