From 879463ebd6796a585589152709a485675834fbc6 Mon Sep 17 00:00:00 2001 From: sunnynagavo Date: Thu, 28 May 2026 18:45:53 +0100 Subject: [PATCH 1/3] docs(dhi): add .NET and Java migration examples Adds before/after Dockerfile examples for migrating .NET and Java applications to Docker Hardened Images, following the existing Go/Python/Node.js examples format. Updates the examples index grid to include the new guides. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../manuals/dhi/migration/examples/_index.md | 8 + .../manuals/dhi/migration/examples/dotnet.md | 157 ++++++++++++++++++ .../manuals/dhi/migration/examples/java.md | 149 +++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 content/manuals/dhi/migration/examples/dotnet.md create mode 100644 content/manuals/dhi/migration/examples/java.md diff --git a/content/manuals/dhi/migration/examples/_index.md b/content/manuals/dhi/migration/examples/_index.md index a1f86e2cfaa..fb35a8c58d3 100644 --- a/content/manuals/dhi/migration/examples/_index.md +++ b/content/manuals/dhi/migration/examples/_index.md @@ -17,6 +17,14 @@ params: description: Learn how to migrate Node.js applications to Docker Hardened Images with practical examples and best practices. icon: code-bracket link: /dhi/migration/examples/node/ + - title: .NET + description: Learn how to migrate .NET applications to Docker Hardened Images with practical examples and best practices. + icon: code-bracket + link: /dhi/migration/examples/dotnet/ + - title: Java + description: Learn how to migrate Java applications to Docker Hardened Images with practical examples and best practices. + icon: code-bracket + link: /dhi/migration/examples/java/ --- This section provides detailed migration examples for common programming languages and frameworks. diff --git a/content/manuals/dhi/migration/examples/dotnet.md b/content/manuals/dhi/migration/examples/dotnet.md new file mode 100644 index 00000000000..3b3b26d3f12 --- /dev/null +++ b/content/manuals/dhi/migration/examples/dotnet.md @@ -0,0 +1,157 @@ +--- +title: .NET +description: Migrate a .NET application to Docker Hardened Images +weight: 40 +keywords: dotnet, .net, csharp, aspnet, migration, dhi +--- + +This example shows how to migrate a .NET application to Docker Hardened Images. + +The following examples show Dockerfiles before and after migration to Docker +Hardened Images. Each example includes five variations: + +- Before (Ubuntu): A sample Dockerfile using Ubuntu-based images, before migrating to DHI +- Before (Wolfi): A sample Dockerfile using Wolfi distribution images, before migrating to DHI +- Before (DOI): A sample Dockerfile using Docker Official Images, before migrating to DHI +- After (multi-stage): A sample Dockerfile after migrating to DHI with multi-stage builds (recommended for minimal, secure images) +- After (single-stage): A sample Dockerfile after migrating to DHI with single-stage builds (simpler but results in a larger image with a broader attack surface) + +> [!NOTE] +> +> Multi-stage builds are recommended for most use cases. Single-stage builds are +> supported for simplicity, but come with tradeoffs in size and security. +> +> You must authenticate to `dhi.io` before you can pull Docker Hardened Images. +> Use your Docker ID credentials (the same username and password you use for +> Docker Hub). If you don't have a Docker account, [create +> one](../../../accounts/create-account.md) for free. +> +> Run `docker login dhi.io` to authenticate. + +{{< tabs >}} +{{< tab name="Before (Ubuntu)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM ubuntu/dotnet-sdk:8.0-24.04 AS builder + +WORKDIR /src +COPY . ./ + +# Install any additional packages if needed using apt +# RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* + +RUN dotnet restore +RUN dotnet publish -c Release -o /app --no-restore + +FROM ubuntu/dotnet-aspnet:8.0-24.04 + +WORKDIR /app +COPY --from=builder /app ./ + +ENTRYPOINT ["dotnet", "app.dll"] +``` + +{{< /tab >}} +{{< tab name="Before (Wolfi)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM cgr.dev/chainguard/dotnet-sdk:latest-dev AS builder + +WORKDIR /src +COPY . ./ + +# Install any additional packages if needed using apk +# RUN apk add --no-cache git + +RUN dotnet restore +RUN dotnet publish -c Release -o /app --no-restore + +FROM cgr.dev/chainguard/aspnet-runtime:latest + +WORKDIR /app +COPY --from=builder /app ./ + +ENTRYPOINT ["dotnet", "app.dll"] +``` + +{{< /tab >}} +{{< tab name="Before (DOI)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS builder + +WORKDIR /src +COPY . ./ + +# Install any additional packages if needed using apt +# RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* + +RUN dotnet restore +RUN dotnet publish -c Release -o /app --no-restore + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 + +WORKDIR /app +COPY --from=builder /app ./ + +ENTRYPOINT ["dotnet", "app.dll"] +``` + +{{< /tab >}} +{{< tab name="After (multi-stage)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +# === Build stage: Restore, build, and publish the .NET application === +FROM dhi.io/dotnet-sdk:8-alpine3.21-dev AS builder + +WORKDIR /src +COPY . ./ + +# Install any additional packages if needed using apk +# RUN apk add --no-cache git + +RUN dotnet restore +RUN dotnet publish -c Release -o /app --no-restore + +# === Final stage: Create minimal runtime image === +FROM dhi.io/dotnet-aspnet:8-alpine3.21 + +WORKDIR /app +COPY --from=builder /app ./ + +ENTRYPOINT ["dotnet", "app.dll"] +``` + +{{< /tab >}} +{{< tab name="After (single-stage)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM dhi.io/dotnet-sdk:8-alpine3.21-dev + +WORKDIR /src +COPY . ./ + +# Install any additional packages if needed using apk +# RUN apk add --no-cache git + +RUN dotnet restore +RUN dotnet publish -c Release -o /app --no-restore + +WORKDIR /app +RUN cp -r /src/bin/Release/net8.0/publish/* /app/ 2>/dev/null || true + +ENTRYPOINT ["dotnet", "/app/app.dll"] +``` + +{{< /tab >}} +{{< /tabs >}} diff --git a/content/manuals/dhi/migration/examples/java.md b/content/manuals/dhi/migration/examples/java.md new file mode 100644 index 00000000000..d2107bcdbcc --- /dev/null +++ b/content/manuals/dhi/migration/examples/java.md @@ -0,0 +1,149 @@ +--- +title: Java +description: Migrate a Java application to Docker Hardened Images +weight: 50 +keywords: java, jvm, jdk, jre, maven, migration, dhi +--- + +This example shows how to migrate a Java application to Docker Hardened Images. + +The following examples show Dockerfiles before and after migration to Docker +Hardened Images. Each example includes five variations: + +- Before (Ubuntu): A sample Dockerfile using Ubuntu-based images, before migrating to DHI +- Before (Wolfi): A sample Dockerfile using Wolfi distribution images, before migrating to DHI +- Before (DOI): A sample Dockerfile using Docker Official Images, before migrating to DHI +- After (multi-stage): A sample Dockerfile after migrating to DHI with multi-stage builds (recommended for minimal, secure images) +- After (single-stage): A sample Dockerfile after migrating to DHI with single-stage builds (simpler but results in a larger image with a broader attack surface) + +> [!NOTE] +> +> Multi-stage builds are recommended for most use cases. Single-stage builds are +> supported for simplicity, but come with tradeoffs in size and security. +> +> You must authenticate to `dhi.io` before you can pull Docker Hardened Images. +> Use your Docker ID credentials (the same username and password you use for +> Docker Hub). If you don't have a Docker account, [create +> one](../../../accounts/create-account.md) for free. +> +> Run `docker login dhi.io` to authenticate. + +{{< tabs >}} +{{< tab name="Before (Ubuntu)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM ubuntu/jre:21-24.04 AS builder + +WORKDIR /app +COPY . ./ + +# Install any additional packages if needed using apt +# RUN apt-get update && apt-get install -y maven && rm -rf /var/lib/apt/lists/* + +RUN mvn -B package -DskipTests + +FROM ubuntu/jre:21-24.04 + +WORKDIR /app +COPY --from=builder /app/target/app.jar /app/app.jar + +ENTRYPOINT ["java", "-jar", "/app/app.jar"] +``` + +{{< /tab >}} +{{< tab name="Before (Wolfi)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM cgr.dev/chainguard/maven:latest-dev AS builder + +WORKDIR /app +COPY . ./ + +# Install any additional packages if needed using apk +# RUN apk add --no-cache git + +RUN mvn -B package -DskipTests + +FROM cgr.dev/chainguard/jre:latest + +WORKDIR /app +COPY --from=builder /app/target/app.jar /app/app.jar + +ENTRYPOINT ["java", "-jar", "/app/app.jar"] +``` + +{{< /tab >}} +{{< tab name="Before (DOI)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM maven:3.9-eclipse-temurin-21 AS builder + +WORKDIR /app +COPY . ./ + +# Install any additional packages if needed using apt +# RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* + +RUN mvn -B package -DskipTests + +FROM eclipse-temurin:21-jre + +WORKDIR /app +COPY --from=builder /app/target/app.jar /app/app.jar + +ENTRYPOINT ["java", "-jar", "/app/app.jar"] +``` + +{{< /tab >}} +{{< tab name="After (multi-stage)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +# === Build stage: Compile and package the Java application with Maven === +FROM dhi.io/maven:3-alpine3.21-dev AS builder + +WORKDIR /app +COPY . ./ + +# Install any additional packages if needed using apk +# RUN apk add --no-cache git + +RUN mvn -B package -DskipTests + +# === Final stage: Create minimal runtime image === +FROM dhi.io/eclipse-temurin:21-alpine3.21 + +WORKDIR /app +COPY --from=builder /app/target/app.jar /app/app.jar + +ENTRYPOINT ["java", "-jar", "/app/app.jar"] +``` + +{{< /tab >}} +{{< tab name="After (single-stage)" >}} + +```dockerfile +#syntax=docker/dockerfile:1 + +FROM dhi.io/maven:3-alpine3.21-dev + +WORKDIR /app +COPY . ./ + +# Install any additional packages if needed using apk +# RUN apk add --no-cache git + +RUN mvn -B package -DskipTests + +ENTRYPOINT ["java", "-jar", "/app/target/app.jar"] +``` + +{{< /tab >}} +{{< /tabs >}} From 13cb341a75844492c3569c6037cc2fa104db2d6e Mon Sep 17 00:00:00 2001 From: "Santhosh Reddy Vootukuri (SUNNY)" Date: Fri, 29 May 2026 17:44:30 +0100 Subject: [PATCH 2/3] docs(dhi): fix unverified images and broken examples in migration docs Apply verified fixes from craig-osterhout/dotnet-java-dhi-verify so the .NET and Java migration examples actually build and run. Java (java.md): - Before (Ubuntu): switch builder + runtime to ubuntu:24.04 and install JDK/Maven (and JRE) via apt. The ubuntu/jre and ubuntu/jdk Pebble-based images have no shell or mvn and fail mvn -B package immediately. - After (multi-stage): update DHI image refs to dhi.io/maven:3-jdk21-alpine3.22-dev and dhi.io/eclipse-temurin:21-alpine3.22 (the alpine3.21 tags do not exist). - After (single-stage): same maven image update. .NET (dotnet.md): - Remove the Before (Ubuntu) tab. ubuntu/dotnet-sdk:8.0-24.04 does not exist; Canonical does not publish a .NET SDK image. Update the intro to describe four variations instead of five. - Before (Wolfi): publish to /src/out and COPY from there. Chainguard images run as non-root and cannot create /app at publish time. - After (multi-stage): update DHI image refs to dhi.io/dotnet:8-sdk-alpine3.22 and dhi.io/aspnetcore:8-alpine3.22. - After (single-stage): update DHI image ref and remove redundant cp -r /src/bin/.../publish/* /app/ 2>/dev/null || true step, since dotnet publish -o /app already writes directly to /app. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../manuals/dhi/migration/examples/dotnet.md | 39 +++---------------- .../manuals/dhi/migration/examples/java.md | 15 +++---- 2 files changed, 14 insertions(+), 40 deletions(-) diff --git a/content/manuals/dhi/migration/examples/dotnet.md b/content/manuals/dhi/migration/examples/dotnet.md index 3b3b26d3f12..79cdee998e1 100644 --- a/content/manuals/dhi/migration/examples/dotnet.md +++ b/content/manuals/dhi/migration/examples/dotnet.md @@ -8,9 +8,8 @@ keywords: dotnet, .net, csharp, aspnet, migration, dhi This example shows how to migrate a .NET application to Docker Hardened Images. The following examples show Dockerfiles before and after migration to Docker -Hardened Images. Each example includes five variations: +Hardened Images. Each example includes four variations: -- Before (Ubuntu): A sample Dockerfile using Ubuntu-based images, before migrating to DHI - Before (Wolfi): A sample Dockerfile using Wolfi distribution images, before migrating to DHI - Before (DOI): A sample Dockerfile using Docker Official Images, before migrating to DHI - After (multi-stage): A sample Dockerfile after migrating to DHI with multi-stage builds (recommended for minimal, secure images) @@ -29,31 +28,6 @@ Hardened Images. Each example includes five variations: > Run `docker login dhi.io` to authenticate. {{< tabs >}} -{{< tab name="Before (Ubuntu)" >}} - -```dockerfile -#syntax=docker/dockerfile:1 - -FROM ubuntu/dotnet-sdk:8.0-24.04 AS builder - -WORKDIR /src -COPY . ./ - -# Install any additional packages if needed using apt -# RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* - -RUN dotnet restore -RUN dotnet publish -c Release -o /app --no-restore - -FROM ubuntu/dotnet-aspnet:8.0-24.04 - -WORKDIR /app -COPY --from=builder /app ./ - -ENTRYPOINT ["dotnet", "app.dll"] -``` - -{{< /tab >}} {{< tab name="Before (Wolfi)" >}} ```dockerfile @@ -68,12 +42,12 @@ COPY . ./ # RUN apk add --no-cache git RUN dotnet restore -RUN dotnet publish -c Release -o /app --no-restore +RUN dotnet publish -c Release -o /src/out --no-restore FROM cgr.dev/chainguard/aspnet-runtime:latest WORKDIR /app -COPY --from=builder /app ./ +COPY --from=builder /src/out ./ ENTRYPOINT ["dotnet", "app.dll"] ``` @@ -110,7 +84,7 @@ ENTRYPOINT ["dotnet", "app.dll"] #syntax=docker/dockerfile:1 # === Build stage: Restore, build, and publish the .NET application === -FROM dhi.io/dotnet-sdk:8-alpine3.21-dev AS builder +FROM dhi.io/dotnet:8-sdk-alpine3.22 AS builder WORKDIR /src COPY . ./ @@ -122,7 +96,7 @@ RUN dotnet restore RUN dotnet publish -c Release -o /app --no-restore # === Final stage: Create minimal runtime image === -FROM dhi.io/dotnet-aspnet:8-alpine3.21 +FROM dhi.io/aspnetcore:8-alpine3.22 WORKDIR /app COPY --from=builder /app ./ @@ -136,7 +110,7 @@ ENTRYPOINT ["dotnet", "app.dll"] ```dockerfile #syntax=docker/dockerfile:1 -FROM dhi.io/dotnet-sdk:8-alpine3.21-dev +FROM dhi.io/dotnet:8-sdk-alpine3.22 WORKDIR /src COPY . ./ @@ -148,7 +122,6 @@ RUN dotnet restore RUN dotnet publish -c Release -o /app --no-restore WORKDIR /app -RUN cp -r /src/bin/Release/net8.0/publish/* /app/ 2>/dev/null || true ENTRYPOINT ["dotnet", "/app/app.dll"] ``` diff --git a/content/manuals/dhi/migration/examples/java.md b/content/manuals/dhi/migration/examples/java.md index d2107bcdbcc..bfae595dc48 100644 --- a/content/manuals/dhi/migration/examples/java.md +++ b/content/manuals/dhi/migration/examples/java.md @@ -34,17 +34,18 @@ Hardened Images. Each example includes five variations: ```dockerfile #syntax=docker/dockerfile:1 -FROM ubuntu/jre:21-24.04 AS builder +FROM ubuntu:24.04 AS builder WORKDIR /app COPY . ./ -# Install any additional packages if needed using apt -# RUN apt-get update && apt-get install -y maven && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y default-jdk maven --no-install-recommends && rm -rf /var/lib/apt/lists/* RUN mvn -B package -DskipTests -FROM ubuntu/jre:21-24.04 +FROM ubuntu:24.04 + +RUN apt-get update && apt-get install -y default-jre --no-install-recommends && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=builder /app/target/app.jar /app/app.jar @@ -107,7 +108,7 @@ ENTRYPOINT ["java", "-jar", "/app/app.jar"] #syntax=docker/dockerfile:1 # === Build stage: Compile and package the Java application with Maven === -FROM dhi.io/maven:3-alpine3.21-dev AS builder +FROM dhi.io/maven:3-jdk21-alpine3.22-dev AS builder WORKDIR /app COPY . ./ @@ -118,7 +119,7 @@ COPY . ./ RUN mvn -B package -DskipTests # === Final stage: Create minimal runtime image === -FROM dhi.io/eclipse-temurin:21-alpine3.21 +FROM dhi.io/eclipse-temurin:21-alpine3.22 WORKDIR /app COPY --from=builder /app/target/app.jar /app/app.jar @@ -132,7 +133,7 @@ ENTRYPOINT ["java", "-jar", "/app/app.jar"] ```dockerfile #syntax=docker/dockerfile:1 -FROM dhi.io/maven:3-alpine3.21-dev +FROM dhi.io/maven:3-jdk21-alpine3.22-dev WORKDIR /app COPY . ./ From 7074b732df569aaf0a7420bad661bbd742ede5e1 Mon Sep 17 00:00:00 2001 From: "Santhosh Reddy Vootukuri (SUNNY)" Date: Fri, 29 May 2026 17:44:57 +0100 Subject: [PATCH 3/3] docs(dhi): add contributor acknowledgment to .NET and Java migration examples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- content/manuals/dhi/migration/examples/dotnet.md | 4 ++++ content/manuals/dhi/migration/examples/java.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/content/manuals/dhi/migration/examples/dotnet.md b/content/manuals/dhi/migration/examples/dotnet.md index 79cdee998e1..0f2f9716f52 100644 --- a/content/manuals/dhi/migration/examples/dotnet.md +++ b/content/manuals/dhi/migration/examples/dotnet.md @@ -5,6 +5,10 @@ weight: 40 keywords: dotnet, .net, csharp, aspnet, migration, dhi --- +> **Acknowledgment** +> +> Docker would like to thank [Naga Santhosh Reddy Vootukuri](https://github.com/sunnynagavo) for his contribution to this guide. + This example shows how to migrate a .NET application to Docker Hardened Images. The following examples show Dockerfiles before and after migration to Docker diff --git a/content/manuals/dhi/migration/examples/java.md b/content/manuals/dhi/migration/examples/java.md index bfae595dc48..e6ab388b359 100644 --- a/content/manuals/dhi/migration/examples/java.md +++ b/content/manuals/dhi/migration/examples/java.md @@ -5,6 +5,10 @@ weight: 50 keywords: java, jvm, jdk, jre, maven, migration, dhi --- +> **Acknowledgment** +> +> Docker would like to thank [Naga Santhosh Reddy Vootukuri](https://github.com/sunnynagavo) for his contribution to this guide. + This example shows how to migrate a Java application to Docker Hardened Images. The following examples show Dockerfiles before and after migration to Docker