Skip to content

Migrate Dockerfile to Docker Hardened Images (DHI) #306

Description

@nanotaboada

Problem

The current Dockerfile uses maven:3.9-eclipse-temurin-25-alpine (builder) and eclipse-temurin:25-jdk-alpine (runtime). Using the full JDK at runtime ships compiler tooling, javac, jshell, and debug utilities that are never used, unnecessarily inflating the image and the attack surface.

Pain points with the current approach:

  • Full JDK at runtime is the primary driver of Java's large image size in this comparison study
  • Known CVEs in base images requiring constant monitoring
  • No built-in SBOM, provenance attestations, or SLSA compliance
  • Manual security update maintenance

Proposed Solution

Migrate to Docker Hardened Images (DHI), using a JRE-based runtime image (not JDK) to reduce both attack surface and image size in a single step.

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)

Suggested Approach

1. Update base images

Builder stage:

# Replace:
FROM maven:3.9-eclipse-temurin-25-alpine AS builder

# With:
FROM dhi.io/eclipse-temurin:25-jdk-alpine-dev AS builder

Runtime stage:

# Replace:
FROM eclipse-temurin:25-jdk-alpine AS runtime

# With:
FROM dhi.io/eclipse-temurin:25-jre-alpine AS runtime

Switching from jdk to jre in the runtime is a direct size win bundled into this migration. For an even smaller image, see the dedicated jlink issue.

2. Adapt health check

Verify curl availability in the DHI Alpine JRE variant. If unavailable:

Option A: Replace with a Java-based HTTP check in healthcheck.sh.
Option B: Explicitly install curl via apk add --no-cache curl.

3. Key files to modify

  • Dockerfile — update base images, verify apk add curl compatibility
  • scripts/healthcheck.sh — adapt if removing curl dependency
  • .github/workflows/maven.yml — update CI/CD if dhi.io authentication is needed

4. Architecture considerations

  • Multi-stage build preserved
  • Non-root spring user maintained
  • /storage volume mount unchanged
  • SQLite runtime libs (sqlite-libs) still required via apk
  • No application code changes required

Note: relationship to other Docker optimization issues

This issue focuses on security hardening. The jlink issue addresses the primary size reduction (full JDK → custom minimal JRE). Both can be implemented independently; jlink provides deeper size savings than the JDK→JRE switch bundled here.

Acceptance Criteria

  • Application builds successfully using DHI base images
  • All existing endpoints function identically
  • Container starts, serves on port 9000/9001, and stops correctly
  • Health check passes consistently
  • Volume mount (/storage) works correctly
  • Non-root user (spring) 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

Activity

  1. added
    enhancementNew feature or request
    javaPull requests that update Java code
    containersPull requests that update containers code
    priority:lowNice-to-have improvement. Can be deferred without blocking other work.
    on Apr 8, 2026
  2. coderabbitai commented on Apr 8, 2026

    @coderabbitai
    🔗 Related PRs

    #162 - chore(ci): simplify Java CI workflow [merged]
    #171 - fix(ci): migrate workflow from adopt to temurin [merged]
    #195 - feat: add multi-stage Dockerfile for building and running app [merged]
    #287 - ci(release): implement named releases with tag-based deployment (#252) [merged]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  3. nanotaboada commented on Apr 9, 2026

    @nanotaboada
    OwnerAuthor

    After further review, we've decided not to implement this change.

    The security and compliance benefits of Docker Hardened Images (SBOM, provenance attestations, SLSA Build Level 3) are well-suited for production systems with formal compliance requirements. However, this project is educational in nature — the primary artifact is the source code, not the container image. The tradeoff doesn't justify the added friction:

    • Rebuilding the image locally requires a one-time docker login dhi.io, since dhi.io requires authentication even for public images — unlike standard Docker Hub pulls
    • Two additional CI/CD secrets (DHI_USERNAME / DHI_PASSWORD) to maintain across all six repos
    • Introduces a dependency on a third-party registry (dhi.io) with its own availability surface

    The existing Alpine-based images remain lean and sufficient for the project's goals. Closing as wontfix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    containersPull requests that update containers codeenhancementNew feature or requestjavaPull requests that update Java codepriority: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