diff --git a/DOCKERHUB.md b/DOCKERHUB.md index 21e0467..aa223f7 100644 --- a/DOCKERHUB.md +++ b/DOCKERHUB.md @@ -46,9 +46,9 @@ Minimal .NET Docker images for production and CI/CD. Built on [Wolfi](https://wo ARG BUILDPLATFORM FROM --platform=$BUILDPLATFORM svrnty/dotnet:sdk-10 AS build -WORKDIR /source -COPY . . -WORKDIR /source/MyApp.Api +WORKDIR /app/source +COPY --chown=nonroot . . +WORKDIR /app/source/MyApp.Api ARG TARGETARCH RUN case "$TARGETARCH" in \ @@ -56,11 +56,11 @@ RUN case "$TARGETARCH" in \ arm64) ARCH=arm64 ;; \ *) ARCH=$TARGETARCH ;; \ esac && \ - dotnet publish -a $ARCH --self-contained false -o /app + dotnet publish -a $ARCH --self-contained false -o /app/publish FROM svrnty/dotnet:runtime-invariant-10 AS final WORKDIR /app -COPY --from=build /app . +COPY --from=build /app/publish . USER 65532 EXPOSE 8080 ENTRYPOINT ["/usr/share/dotnet/dotnet", "MyApp.Api.dll"] @@ -72,8 +72,8 @@ ENTRYPOINT ["/usr/share/dotnet/dotnet", "MyApp.Api.dll"] ARG BUILDPLATFORM FROM --platform=$BUILDPLATFORM svrnty/dotnet:sdk-lts AS build -WORKDIR /source -COPY . . +WORKDIR /app/source +COPY --chown=nonroot . . ARG TARGETARCH RUN case "$TARGETARCH" in \ @@ -81,11 +81,11 @@ RUN case "$TARGETARCH" in \ arm64) ARCH=arm64 ;; \ *) ARCH=$TARGETARCH ;; \ esac && \ - dotnet publish MyWorker -a $ARCH --self-contained false -o /app + dotnet publish MyWorker -a $ARCH --self-contained false -o /app/publish FROM svrnty/dotnet:runtime-invariant-lts AS final WORKDIR /app -COPY --from=build /app . +COPY --from=build /app/publish . USER 65532 ENTRYPOINT ["/usr/share/dotnet/dotnet", "MyWorker.dll"] ``` diff --git a/README.md b/README.md index bf874dd..c1a16db 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ Minimal .NET Docker images for production and CI/CD. Built on [Wolfi](https://wo |---------|----------|-------|-------------------|------| | **runtime** | ASP.NET Core runtime | No | Yes | 65532 (nonroot) | | **runtime-invariant** | ASP.NET Core runtime | No | No (invariant mode) | 65532 (nonroot) | -| **sdk** | .NET SDK + bash, git, curl | Yes (bash) | Yes | root | +| **sdk** | .NET SDK + bash, git, curl | Yes (bash) | Yes | 65532 (nonroot) | - **runtime** - Full globalization support (ICU + tzdata). Use this for apps that need locale-aware formatting, time zones, or culture-specific behavior. - **runtime-invariant** - No ICU or tzdata. Smallest image size. Use this for APIs that only need UTC and ordinal string comparison. -- **sdk** - Everything needed to build .NET apps. Runs as root so `dotnet restore` can write to global caches. +- **sdk** - Everything needed to build .NET apps. Uses `DOTNET_CLI_HOME=/home/nonroot` for NuGet cache — no root required. Use `COPY --chown=nonroot` to make source files writable. ## Why Wolfi? @@ -51,9 +51,9 @@ Minimal .NET Docker images for production and CI/CD. Built on [Wolfi](https://wo ARG BUILDPLATFORM FROM --platform=$BUILDPLATFORM svrnty/dotnet:sdk-10 AS build -WORKDIR /source -COPY . . -WORKDIR /source/MyApp.Api +WORKDIR /app/source +COPY --chown=nonroot . . +WORKDIR /app/source/MyApp.Api ARG TARGETARCH RUN case "$TARGETARCH" in \ @@ -61,11 +61,11 @@ RUN case "$TARGETARCH" in \ arm64) ARCH=arm64 ;; \ *) ARCH=$TARGETARCH ;; \ esac && \ - dotnet publish -a $ARCH --self-contained false -o /app + dotnet publish -a $ARCH --self-contained false -o /app/publish FROM svrnty/dotnet:runtime-invariant-10 AS final WORKDIR /app -COPY --from=build /app . +COPY --from=build /app/publish . USER 65532 EXPOSE 8080 ENTRYPOINT ["/usr/share/dotnet/dotnet", "MyApp.Api.dll"] @@ -77,8 +77,8 @@ ENTRYPOINT ["/usr/share/dotnet/dotnet", "MyApp.Api.dll"] ARG BUILDPLATFORM FROM --platform=$BUILDPLATFORM svrnty/dotnet:sdk-lts AS build -WORKDIR /source -COPY . . +WORKDIR /app/source +COPY --chown=nonroot . . ARG TARGETARCH RUN case "$TARGETARCH" in \ @@ -86,11 +86,11 @@ RUN case "$TARGETARCH" in \ arm64) ARCH=arm64 ;; \ *) ARCH=$TARGETARCH ;; \ esac && \ - dotnet publish MyApp.sln -a $ARCH --self-contained false -o /app + dotnet publish MyApp.sln -a $ARCH --self-contained false -o /app/publish FROM svrnty/dotnet:runtime-lts AS final WORKDIR /app -COPY --from=build /app . +COPY --from=build /app/publish . USER 65532 EXPOSE 8080 ENTRYPOINT ["/usr/share/dotnet/dotnet", "MyApp.dll"] @@ -102,8 +102,8 @@ ENTRYPOINT ["/usr/share/dotnet/dotnet", "MyApp.dll"] ARG BUILDPLATFORM FROM --platform=$BUILDPLATFORM svrnty/dotnet:sdk-10 AS build -WORKDIR /source -COPY . . +WORKDIR /app/source +COPY --chown=nonroot . . ARG TARGETARCH RUN case "$TARGETARCH" in \ @@ -111,11 +111,11 @@ RUN case "$TARGETARCH" in \ arm64) ARCH=arm64 ;; \ *) ARCH=$TARGETARCH ;; \ esac && \ - dotnet publish MyWorker -a $ARCH --self-contained false -o /app + dotnet publish MyWorker -a $ARCH --self-contained false -o /app/publish FROM svrnty/dotnet:runtime-invariant-10 AS final WORKDIR /app -COPY --from=build /app . +COPY --from=build /app/publish . USER 65532 ENTRYPOINT ["/usr/share/dotnet/dotnet", "MyWorker.dll"] ``` diff --git a/apko/sdk.yaml b/apko/sdk.yaml index 612b227..8b804f9 100644 --- a/apko/sdk.yaml +++ b/apko/sdk.yaml @@ -25,7 +25,19 @@ accounts: - username: nonroot uid: 65532 gid: 65532 - run-as: 0 + run-as: 65532 + +paths: + - path: /home/nonroot + type: directory + uid: 65532 + gid: 65532 + permissions: 0o755 + - path: /app + type: directory + uid: 65532 + gid: 65532 + permissions: 0o755 archs: - x86_64 diff --git a/dockerfiles/sdk.Dockerfile b/dockerfiles/sdk.Dockerfile index b1a5fd6..75b7790 100644 --- a/dockerfiles/sdk.Dockerfile +++ b/dockerfiles/sdk.Dockerfile @@ -6,5 +6,7 @@ ENV DOTNET_ROOT=/usr/share/dotnet ENV PATH="/usr/share/dotnet:${PATH}" ENV DOTNET_RUNNING_IN_CONTAINER=true ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false +ENV HOME=/home/nonroot +ENV DOTNET_CLI_HOME=/home/nonroot WORKDIR /app -USER 0 +USER 65532