Skip to content

Migrate Dockerfile to Docker Hardened Images (DHI) #455

@nanotaboada

Description

@nanotaboada

Problem

The current Dockerfile uses mcr.microsoft.com/dotnet/sdk:10.0 (builder) and mcr.microsoft.com/dotnet/aspnet:10.0 (runtime), both Debian-based, which carry known CVEs and a larger attack surface than necessary for production deployments.

Pain points with the current approach:

  • CVEs in base images requiring constant monitoring and patching
  • No built-in SBOM (Software Bill of Materials) or provenance attestations
  • No formal security compliance certifications (SLSA, CIS benchmarks)
  • Larger attack surface from unnecessary packages in the Debian base
  • Manual effort required to stay current with security updates

Proposed Solution

Migrate the Dockerfile to use Docker Hardened Images (DHI) — Docker's official minimal, security-hardened base images — for both stages.

DHI provides:

  • Up to 95% reduction in attack surface vs. standard images
  • Near-zero CVEs, actively maintained by Docker's security team
  • Built-in SBOM, provenance attestations, SLSA Build Level 3
  • Free and open source (Apache 2.0)

Expected behavior after implementation:

  • Application continues to function identically
  • Dramatically reduced vulnerability count in base images
  • Full supply chain transparency with built-in attestations

Suggested Approach

1. Update base images

Builder stage:

# Replace:
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS builder

# With:
FROM dhi.io/dotnet/sdk:10.0-debian13-dev AS builder

Runtime stage:

# Replace:
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime

# With:
FROM dhi.io/dotnet/aspnet:10.0-debian13 AS runtime

2. Adapt health check

DHI runtime images are minimal and do not include curl by default. The current apt-get install curl layer should be removed or replaced.

Option A (recommended): Replace curl with a .NET-based HTTP call in healthcheck.sh:

#!/bin/sh
dotnet-httpclient http://localhost:9000/health || exit 1

Or use wget if available in the DHI variant.

Option B: Install curl explicitly in the runtime stage (verify availability in DHI Debian variant).

3. Key files to modify

  • Dockerfile — update base images, replace apt-get curl install
  • scripts/healthcheck.sh — adapt health check if removing curl
  • .github/workflows/dotnet.yml — update CI/CD if dhi.io authentication is needed

4. Architecture considerations

  • Multi-stage build preserved
  • Non-root aspnetcore user maintained
  • /storage volume mount unchanged
  • No application code changes required

Note: relationship to other Docker optimization issues

This issue focuses on security hardening. A separate issue covers switching the runtime to aspnet:10.0-alpine for a ~100–150 MB size reduction. Both can be implemented together or sequentially.

Acceptance Criteria

  • Application builds successfully using DHI base images
  • All existing endpoints function identically
  • Container starts, serves on port 9000, and stops correctly
  • Health check passes consistently
  • Volume mount (/storage) works correctly
  • Non-root user (aspnetcore) has correct permissions
  • Docker Scout scan shows significantly reduced CVE count vs. previous image
  • SBOM is present and complete (docker buildx imagetools inspect --format "{{json .SBOM}}")
  • Provenance attestations are verifiable
  • All CI tests pass against the new image

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    containersPull requests that update containers codedotnetPull requests that update .NET codeenhancementNew feature or requestpriority:lowNice-to-have improvement. Can be deferred without blocking other work.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions