Making the Most of Your Docker Hardened Images Enterprise Trial – Part 3

Customizing Docker Hardened Images

In Part 1 and Part 2, we established the baseline. You migrated a service to a Docker Hardened Image (DHI), witnessed the vulnerability count drop to zero, and verified the cryptographic signatures and SLSA provenance that make DHI a compliant foundation.

But no matter how secure a base image is, it is useless if you can’t run your application on it. This brings us to the most common question engineers ask during a DHI trial: what if I need a custom image?

Hardened images are minimal by design. They lack package managers (apt, apk, yum), utilities (wget, curl), and even shells like bash or sh. This is a security feature: if a bad actor breaks into your container, they find an empty toolbox.

However, developers often need these tools during setup. You might need to install a monitoring agent, a custom CA certificate, or a specific library.

In this final part of our series, we will cover the two strategies for customizing DHI: the Docker Hub UI (for platform teams creating “Golden Images”) and the multi-stage build pattern (for developers building applications).

Option 1: The Golden Image (Docker Hub UI)

If you are a Platform or DevOps Engineer, your goal is likely to provide a “blessed” base image for your internal teams. For example, you might want a standard Node.js image that always includes your corporate root CA certificate and your security logging agent.The Docker Hub UI is the preferred path for this. The strongest argument for using the Hub UI is maintenance automation.

The Killer Feature: Automatic Rebuilds

When you customize an image via the UI, Docker understands the relationship between your custom layers and the hardened base. If Docker releases a patch for the underlying DHI base image (e.g., a fix in glibc or openssl), Docker Hub automatically rebuilds your custom image.

You don’t need to trigger a CI pipeline. You don’t need to monitor CVE feeds. The platform handles the patching and rebuilding, ensuring your “Golden Image” is always compliant with the latest security standards.

How It Works

Since you have an Organization setup for this trial, you can explore this directly in Docker Hub.First, navigate to Repositories in your organization dashboard. Locate the image you want to customize (e.g., dhi-node), then the Customizations tab and click the “Create customization” action. This initiates a customization workflow as follows:

In the “Add packages” section, you can search for and select OS packages directly from the distribution’s repository. For example, here we are adding bash to the image for debugging purposes. You can also add “OCI Artifacts” to inject custom files like certificates or agents.

Finally, configure the runtime settings (User, Environment Variables) and review your build. Docker Hub will verify the configuration and queue the build. Once complete, this image will be available in your organization’s private registry and will automatically rebuild whenever the base DHI image is updated.

This option is best suited for creating standardized “golden” base images that are used across the entire organization. The primary advantage is zero-maintenance security patching due to automatic rebuilds by Docker Hub. However, it is less flexible for rapid, application-specific iteration by individual development teams.

Option 2: Multi-Stage Build

If you are an developper, you likely define your environment in a Dockerfile that lives alongside your code. You need flexibility, and you need it to work locally on your machine.

Since DHI images don’t have apt-get or curl, you cannot simply RUN apt-get install my-lib in your Dockerfile. It will fail.

Instead, we use the multi-stage build pattern. The concept is simple:

Stage 1 (Builder): Use a standard “fat” image (like debian:bookworm-slim) to download, compile, and prepare your dependencies.

Stage 2 (Runtime): Copy only the resulting artifacts into the pristine DHI base.

This keeps your final image minimal, non-root, and secure, while still allowing you to install whatever you need.

Hands-on Tutorial: Adding a Monitoring Agent

Let’s try this locally. We will simulate a common real-world scenario: adding the Datadog APM library (dd-trace) globally to a Node.js DHI image.

1. Setup

Create a new directory for this test and add a simple server.js file. This script attempts to load the dd-trace library to verify our installation.

app/server.js

// Simple Express server to demonstrate DHI customization
console.log('Node.js version:', process.version);
try {
require('dd-trace');
console.log('dd-trace module loaded successfully!');
} catch (e) {
console.error('Failed to load dd-trace:', e.message);
process.exit(1);
}
console.log('Running as UID:', process.getuid(), 'GID:', process.getgid());
console.log('DHI customization test successful!');

2. Hardened Dockerfile

Now, create the Dockerfile. We will use a standard Debian image to install the library, and then copy it to our DHI Node.js image. Create a new directory for this test and add a simple server.js file. This script attempts to load the dd-trace library to verify our installation.

# Stage 1: Builder – a standard Debian Slim image that has apt, curl, and full shell access.
FROM debian:bookworm-slim AS builder

# Install Node.js (matching our target version) and tools
RUN apt-get update &&
apt-get install -y curl &&
curl -fsSL https://deb.nodesource.com/setup_24.x | bash – &&
apt-get install -y nodejs

# Install Datadog APM agent globally (we force the install prefix to /usr/local so we know exactly where files go)
RUN npm config set prefix /usr/local &&
npm install -g dd-trace@5.0.0

# Stage 2: Runtime – we switch to the Docker Hardened Image.
FROM <your-org-namespace>/dhi-node:24.11-debian13-fips

# Copy only the required library from the builder stage
COPY –from=builder /usr/local/lib/node_modules/dd-trace /usr/local/lib/node_modules/dd-trace

# Environment Configuration
# DHI images are strict. We must explicitly tell Node where to find global modules.
ENV NODE_PATH=/usr/local/lib/node_modules

# Copy application code
COPY app/ /app/

WORKDIR /app

# DHI Best Practice: Use the exec form (["node", …])
# because there is no shell to process strings.
CMD ["node", "server.js"]

3. Build and Run

Build the custom image:

docker build -t dhi-monitoring-test .

Now run it. If successful, the container should start, find the library, and exit cleanly.

docker run –rm dhi-monitoring-test

Output:

Node.js version: v24.11.0
dd-trace module loaded successfully!
Running as UID: 1000 GID: 1000
DHI customization test successful!

Success! We have a working application with a custom global library, running on a hardened, non-root base.

Security Check

We successfully customized the image. But did we compromise its security?

This is the most critical lesson of operationalizing DHI: hardened base images protect the OS, but they do not protect you from the code you add.Let’s verify our new image with Docker Scout.

docker scout cves dhi-monitoring-test –only-severity critical,high

Sample Output:

✗ Detected 1 vulnerable package with 1 vulnerability

0C 1H 0M 0L lodash.pick 4.4.0
pkg:npm/lodash.pick@4.4.0

✗ HIGH CVE-2020-8203 [Improperly Controlled Modification of Object Prototype Attributes]

This result is accurate and important. The base image (OS, OpenSSL, Node.js runtime) is still secure. However, the dd-trace library we just installed pulled in a dependency (lodash.pick) that contains a High severity vulnerability.

This proves that your verification pipeline works.

If we hadn’t scanned the custom image, we might have assumed we were safe because we used a “Hardened Image.” By using Docker Scout on the final artifact, we caught a supply chain vulnerability introduced by our customization.

Let’s check how much “bloat” we added compared to the clean base.

docker scout compare –to <your-org-namespace>/dhi-node:24.11-debian13-fips dhi-monitoring-test

You will see that the only added size corresponds to the dd-trace library (~5MB) and our application code. We didn’t accidentally inherit apt, curl, or the build caches from the builder stage. The attack surface remains minimized.

A Note on Provenance: Who Signs What?

In Part 2, we verified the SLSA Provenance and cryptographic signatures of Docker Hardened Images. This is crucial for establishing a trusted supply chain. When you customize an image, the question of who “owns” the signature becomes important.

Docker Hub UI Customization: When you customize an image through the Docker Hub UI, Docker itself acts as the builder for your custom image. This means the resulting customized image inherits signed provenance and attestations directly from Docker’s build infrastructure. If the base DHI receives a security patch, Docker automatically rebuilds and re-signs your custom image, ensuring continuous trust. This is a significant advantage for platform teams creating “golden images.”

Local Dockerfile: When you build a custom image using a multi-stage Dockerfile locally (as we did in our tutorial), you are the builder. Your docker build command produces a new image with a new digest. Consequently, the original DHI signature from Docker does not apply to your final custom image (because the bits have changed and you are the new builder).However, the chain of trust is not entirely broken:

Base Layers: The underlying DHI layers within your custom image still retain their original Docker attestations.

Custom Layer: Your organization is now the “builder” of the new layers.

For production deployments using the multi-stage build, you should integrate Cosign or Docker Content Trust into your CI/CD pipeline to sign your custom images. This closes the loop, allowing you to enforce policies like: “Only run images built by MyOrg, which are based on verified DHI images and have our internal signature.”

Measuring Your ROI: Questions for Your Team

As you conclude your Docker Hardened Images trial, it’s critical to quantify the value for your organization. Reflect on the concrete results from your migration and customization efforts using these questions:

Vulnerability Reduction: How significantly did DHI impact your CVE counts? Compare the “before and after” vulnerability reports for your migrated services. What is the estimated security risk reduction?

Engineering Effort: What was the actual engineering effort required to migrate an image to DHI? Consider the time saved on patching, vulnerability triage, and security reviews compared to managing traditional base images.

Workflow: How well does DHI integrate into your team’s existing development and CI/CD workflows? Do developers find the customization patterns (Golden Image / Builder Pattern) practical and efficient? Is your team likely to adopt this long-term?

Compliance & Audit: Has DHI simplified your compliance reporting or audit processes due to its SLSA provenance and FIPS compliance? What is the impact on your regulatory burden?

Conclusion

Thanks for following through to the end! Over this 3-part blog series, you have moved from a simple trial to a fully operational workflow:

Migration: You replaced a standard base image with DHI and saw immediate vulnerability reduction.

Verification: You independently validated signatures, FIPS compliance, and SBOMs.

Customization: You learned to extend DHI using the Hub UI (for auto-patching) or multi-stage builds, while checking for new vulnerabilities introduced by your own dependencies.

The lesson here is that the “Hardened” in Docker Hardened Images isn’t a magic shield but a clean foundation. By building on top of it, you ensure that your team spends time securing your application code, rather than fighting a never-ending battle against thousands of upstream vulnerabilities.
Quelle: https://blog.docker.com/feed/

Making the Most of Your Docker Hardened Images Enterprise Trial – Part 2

Verifying Security and Compliance of Docker Hardened Images

In Part 1 of this series, we migrated a Node.js service to Docker Hardened Images (DHI) and measured impressive results: 100% vulnerability elimination, 90% package reduction, and 41.5% size decrease. We extracted the SBOM and saw compliance labels for FIPS, STIG, and CIS.

The numbers look compelling. But how do you verify these claims independently?

Security tools earn trust through verification, not promises. When evaluating a security product for production, you need cryptographic proof. This is especially true for images that form the foundation of every container you deploy.This post walks through the verification process: signature validation, provenance analysis, compliance evidence examination, and SBOM analysis. We’ll focus on practical verification you can run during your trial, with links to the official DHI documentation for deeper technical details. By the end, you’ll have independently confirmed DHI’s security posture and built confidence for a production scenario.

Understanding Security Attestations available with Docker Hardened Images

Before diving into verification, you need to understand what you’re verifying.

Docker Hardened Images include attestations: cryptographically-signed metadata about the image’s build process, contents, and compliance posture. These are signed statements that can be independently verified.

Important: If you’ve pulled the image locally, you need to use the registry:// prefix when working with attestations. This tells Docker Scout to look for attestations in the registry, not just the local image cache.

List all attestations for your hardened image:

docker scout attestation list registry://<your-org-namespace>/dhi-node:24.11-debian13-fips

This shows 16 different attestation types:

https://slsa.dev/provenance/v0.2 SLSA provenance
https://docker.com/dhi/fips/v0.1 FIPS compliance
https://docker.com/dhi/stig/v0.1 STIG scan
https://cyclonedx.org/bom/v1.6 CycloneDX SBOM
https://spdx.dev/Document SPDX SBOM
https://scout.docker.com/vulnerabilities Scout vulnerabilities
https://scout.docker.com/secrets/v0.1 Scout secret scan
https://scout.docker.com/virus/v0.1 Scout virus/malware
https://scout.docker.com/tests/v0.1 Scout test report
https://openvex.dev/ns/v0.2.0 OpenVEX

Each attestation is a JSON document describing a specific aspect of the image. The most critical attestations for verification:

SLSA provenance: Build source, builder identity, and build process details

SBOM: Complete software bill of materials

FIPS compliance: Evidence of FIPS 140-3 certified cryptographic modules

STIG scan: Security Technical Implementation Guide compliance results

Vulnerability scan: CVE assessment

VEX report: CVE exploitability

These attestations follow the in-toto specification, an open framework for supply chain security. Each attestation includes:

Subject: What the attestation describes (the container image)

Predicate: The actual claims (FIPS certified, STIG compliant, etc.)

Signature: Cryptographic signature from the builder

Let’s see how you can verify the signatures yourself.

Verifying Attestations with Docker Scout

The attestations we’re about to examine are cryptographically signed by Docker’s build infrastructure. Docker Scout provides a simple, integrated approach that handles DHI attestations natively and without the hassle of managing public keys or certificate chains.To validate an attestation, simply append the –verify flag, which provides explicit validation feedback. This process relies on cryptographic hashing: the digest is a hash of the attestation content, so even a single character change completely alters the hash. Moreover, the attestation’s signature is cryptographically bound to the specific image digest it describes, guaranteeing that the metadata you’re verifying corresponds exactly to the image you have and preventing substitution attacks.

Retrieving an Attestation

To extract a specific attestation (like SLSA provenance), use the attestation get command with the full predicate type URI:

docker scout attestation get registry://<your-org-namespace>/dhi-node:24.11-debian13-fips
–predicate-type https://slsa.dev/provenance/v0.2
–output provenance.json

Success looks like this:

✓ SBOM obtained from attestation, 32 packages found
✓ Provenance obtained from attestation
✓ Report written to provenance.json

The checkmarks confirm Docker Scout successfully retrieved and verified the attestation. Behind the scenes, Scout validated:

The attestation signature matches Docker’s signing key

The signature hasn’t expired

The attestation applies to this specific image digest

The attestation hasn’t been tampered with

If signature verification fails, Scout returns an error and won’t output the attestation file.To learn more about available predicate types, check out the DHI verification documentation.

Validating SLSA Provenance

Signatures prove attestations are authentic. Provenance shows where the image came from.

SLSA (Supply-chain Levels for Software Artifacts) is a security framework developed by Google, the Linux Foundation, and other industry partners. It defines levels of supply chain security maturity, from SLSA 0 (no guarantees) to SLSA 4 (highest assurance).

Docker Hardened Images target SLSA 3, which requires:

Build process fully scripted/automated

All build steps defined in version control

Provenance generated automatically by build service

Provenance includes source, builder, and build parameters

Using our previously extracted SLSA provenance.json, we can check the source repository and commit hash:

jq '.predicate.invocation.environment.github_repository' provenance.json

Output:

"docker-hardened-images/definitions"
jq '.predicate.invocation.environment.github_sha1' provenance.json

Output:

"698b367344efb3a7d443508782de331a84216ae4"

Similarly, you can see exactly what GitHub Actions workflow produced this image.

jq '.predicate.builder.id' provenance.json

Output:

“https://github.com/docker-hardened-images/definitions/actions/runs/18930640220/attempts/1”

For DHI Enterprise Users: Verifying High-Assurance Claims

While the free hardened images are built with security best practices, DHI Enterprise images carry the specific certifications required for FedRAMP, HIPAA, and financial audits. Here is how to verify those high-assurance claims.

FIPS 140-3 Validation

FIPS (Federal Information Processing Standard) 140-3 is a U.S. government standard for cryptographic modules. Think of it as a certification that proves the cryptography in your software has been tested and validated by independent labs against federal requirements.

If you’re building software for government agencies, financial institutions, or healthcare providers, FIPS compliance is often mandatory: without it, your software can’t be used in those environments!

Check if the image includes FIPS-certified cryptography:

docker scout attestation get registry://<your-org-namespace>/dhi-node:24.11-debian13-fips
–predicate-type https://docker.com/dhi/fips/v0.1
–output fips-attestation.json

Output:

{
"certification": "CMVP #4985",
"certificationUrl": "https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4985",
"name": "OpenSSL FIPS Provider",
"package": "pkg:dhi/openssl-provider-fips@3.1.2",
"standard": "FIPS 140-3",
"status": "active",
"sunsetDate": "2030-03-10",
"version": "3.1.2"
}

The certificate number (4985) is the key piece. This references a specific FIPS validation in the official NIST CMVP database.

STIG Compliance

STIG (Security Technical Implementation Guide) is the Department of Defense’s (DoD) checklist for securing systems. It’s a comprehensive security configuration standard needed for deploying software for defense or government work.DHI images undergo STIG scanning before release. Docker uses a custom STIG based on the DoD’s General Operating System Security Requirements Guide. Each scan checks dozens of security controls and reports findings. You can extract and review STIG scan results:

docker scout attestation get registry://<your-org-namespace>/dhi-node:24.11-debian13-fips
–predicate-type https://docker.com/dhi/stig/v0.1
–output stig-attestation.json

Check the STIG scan summary:

jq '.predicate[0].summary' stig-attestation.json

Output:

{
"failedChecks": 0,
"passedChecks": 91,
"notApplicableChecks": 107,
"totalChecks": 198,
"defaultScore": 100,
"flatScore": 91
}

This shows DHI passed all 91 applicable STIG controls with zero failed checks and a 100% score. The 107 “notApplicableChecks” typically refer to controls that are irrelevant to the specific minimal container environment or its configuration. For a complete list of STIG controls and DHI compliance details, including how to extract and view the full STIG scan report, see the DHI STIG documentation.

CIS Benchmark Hardening

CIS (Center for Internet Security) Benchmarks are security configuration standards created by security professionals across industries. Much like STIGs, they represent consensus best practices, but unlike government-mandated frameworks (FIPS, STIG), CIS benchmarks are community-developed.

CIS compliance isn’t legally required, but it demonstrates you’re following industry-standard security practices—valuable for customer trust and audit preparation.

You can verify CIS compliance through image labels:

docker inspect <your-org-namespace>/dhi-node:24.11-debian13-fips |
jq '.[0].Config.Labels["com.docker.dhi.compliance"]'

Output: “fips,stig,cis”

The CIS label indicates that an image is hardened according to the CIS Docker Benchmark.

What exactly is a SBOM used for?

Compliance frameworks tell you what standards you meet. The SBOM tells you what’s actually in your container—and that’s where the real security work begins.

Identifying Transitive Dependencies

When you add a package to your project, you see the direct dependency. What you don’t see: that package’s dependencies, and their dependencies, and so on. This is the transitive dependency problem.

A vulnerability in a transitive dependency you’ve never heard of can compromise your entire application. Real example: the Log4Shell vulnerability affected millions of applications because Log4j was a transitive dependency buried several levels deep in dependency chains.

Most vulnerabilities hide in transitive dependencies because:

Developers don’t know they exist

They’re not updated when the direct dependency updates

Scanning tools miss them without an SBOM

Minimal images reduce this risk dramatically. Fewer packages = fewer transitive dependencies = smaller attack surface.

Compare dependency counts:

Official Node.js image: 321 packages, ~1,500 dependency relationships

DHI Node.js image: 32 packages, ~150 dependency relationships

90% reduction in packages means 90% reduction in transitive dependency risk.

Scanning for Known (Exploitable) Vulnerabilities

With the SBOM extracted, scan for known vulnerabilities:

docker scout cves registry://<your-org-namespace>/dhi-node:24.11-debian13-fips

Output:

Target: <your-org-namespace>/dhi-node:24.11-debian13-fips

0C 0H 0M 8L

8 vulnerabilities found in 2 packages
CRITICAL 0
HIGH 0
MEDIUM 0
LOW 8

Zero critical, high, or medium severity vulnerabilities. Docker Scout cross-references the SBOM against multiple vulnerability databases (NVD, GitHub Security Advisories, etc.).This is the payoff of minimal images: fewer packages means fewer potential vulnerabilities. The official Node.js image had 25 CVEs across CRITICAL, HIGH, and MEDIUM severities. The hardened version has zero actionable vulnerabilities—not because vulnerabilities were patched, but because vulnerable packages were removed entirely.

Understanding Exploitability with VEX

Not all CVEs are relevant to your deployment. A vulnerability in a library function your application never calls, or a flaw in a service that isn’t running, doesn’t pose real risk. Docker Hardened Images include signed VEX attestations that identify which reported CVEs are not actually exploitable in the image’s runtime context. This helps you distinguish between CVEs that exist in a package (reported), and CVEs that can actually be exploited given how the package is used in this specific image (exploitable). In other words, VEX reduces false positives.

Docker Scout applies VEX statements automatically when scanning DHI images: when you run docker scout cves, Scout uses VEX attestations to suppress vulnerabilities marked as non-exploitable.

You can see which CVEs have been evaluated with this command:

docker scout attestation get registry://<your-org-namespace>/dhi-node:24.11-debian13-fips
–predicate-type https://openvex.dev/ns/v0.2.0
–output vex.json

License Compliance Analysis

When you use open source software, you’re bound by license terms. Some licenses (MIT, Apache) are permissive and you can use them freely, even in commercial products. Others (GPL, AGPL) are copyleft: they require you to release your source code if you distribute software using them.

SBOMs make license compliance visible. Without an SBOM, you’re blind to what licenses your containers include.

Export the SBOM in SPDX format:

docker scout sbom registry://<your-org-namespace>/dhi-node:24.11-debian13-fips
–format spdx
–output node-sbom-spdx.json

Analyze license distribution:

jq '.packages[].licenseConcluded' node-sbom-spdx.json |
sort | uniq -c | sort -rn

Output:

15 "MIT"
8 "Apache-2.0"
5 "GPL-2.0-or-later"
2 "BSD-3-Clause"
1 "OpenSSL"
1 "NOASSERTION"

In this example:

✅ MIT and Apache-2.0 are permissive (safe for commercial use)

⚠️ GPL-2.0-or-later requires review (is this a runtime dependency or build tool?)

⚠️ NOASSERTION needs investigation

Conclusion: What You’ve Proven

You’ve independently verified critical security claims Docker makes about Hardened Images:

Authenticity: Cryptographic signatures prove images are genuine and unmodified

Provenance: SLSA attestations trace builds to specific source commits in public repositoriesCompliance: FIPS certificate, STIG controls passed, and CIS benchmarks met

Security posture

Every claim you verified (except CIS) has a corresponding attestation you can check yourself, audit, and validate in your CI/CD pipeline.

You can customize a Docker Hardened Image (DHI) to suit your specific needs using the Docker Hub UI. This allows you to select a base image, add packages, add OCI artifacts (such as custom certificates or additional tools), and configure settings. In addition, the build pipeline ensures that your customized image is built securely and includes attestations.

In Part 3, we’ll cover how to customize Docker Hardened Images to suit your specific needs, while keeping all the benefits we just explored.

You’ve confirmed DHI delivers on security promises. Next, we’ll make it operational.

If you missed reading part 1, where we discussed how you can get to 100% vulnerability elimination and 90% package reduction, read the blog here.

Quelle: https://blog.docker.com/feed/