# syntax=docker/dockerfile:1.7 FROM node:24.18.1-bookworm-slim@sha256:235600a8101ab264e117b1768e925532262668dc9b581ef1dd7d96ced463b8e7 AS web-build WORKDIR /repo RUN corepack enable COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./ COPY src/frontend/package.json src/frontend/package.json COPY tests/e2e/package.json tests/e2e/package.json RUN pnpm install --filter @itworx/knowledge-hub-web... --frozen-lockfile COPY src/frontend src/frontend RUN pnpm --filter @itworx/knowledge-hub-web build # Canonical release identity (docs/adr/ADR-029-v2-r5-final-hardening.md): generated # here, not in the .NET SDK stage, because this is the one build stage that already # has both Node.js and the real built frontend output to hash — never a second, # independently-drifting source of truth. Computed only from what is actually inside # *this* build (source commit, the real docs/api/openapi.yaml, the real dist/ output); # deployment-time-only fields (image tag/ID/digest, deployment timestamp, migration # range) are deliberately left null here — see the script's own header comment. ARG BUILD_COMMIT=development ARG RELEASE_TAG= ARG IMAGE_REPOSITORY=itworx/knowledge-hub ARG IMAGE_TAG= COPY scripts/generate-release-manifest.mjs scripts/generate-release-manifest.mjs COPY docs/api/openapi.yaml docs/api/openapi.yaml RUN BUILD_COMMIT=${BUILD_COMMIT} RELEASE_TAG=${RELEASE_TAG} IMAGE_REPOSITORY=${IMAGE_REPOSITORY} IMAGE_TAG=${IMAGE_TAG} \ node scripts/generate-release-manifest.mjs /repo/release-manifest.json FROM mcr.microsoft.com/dotnet/sdk:10.0.302-noble@sha256:72dd743782f2ae7e5476fd64f6a460045e3998dc862218b80e6944cba79a01b0 AS backend-build WORKDIR /repo COPY global.json Directory.Build.props Directory.Build.targets Directory.Packages.props NuGet.Config .editorconfig ./ COPY ItWorx.KnowledgeHub.slnx ./ COPY src/backend src/backend COPY tests/backend tests/backend RUN dotnet restore ItWorx.KnowledgeHub.slnx RUN dotnet publish \ src/backend/ItWorx.KnowledgeHub.Api/ItWorx.KnowledgeHub.Api.csproj \ --configuration Release \ --no-restore \ --output /app/publish \ /p:UseAppHost=false RUN rm -rf /app/publish/wwwroot/* COPY --from=web-build /repo/src/frontend/dist /app/publish/wwwroot COPY --from=web-build /repo/release-manifest.json /app/publish/release-manifest.json FROM mcr.microsoft.com/dotnet/aspnet:10.0.11-noble@sha256:a4556ed033fa96f984bb7a8d348851cb2d36b1281dd2420070045f664fbb5f94 AS runtime ARG BUILD_COMMIT=development ENV ASPNETCORE_URLS=http://0.0.0.0:8080 \ DOTNET_EnableDiagnostics=0 \ Build__Commit=${BUILD_COMMIT} # Explicitly refresh OpenSSL too: the pinned base may predate security # updates even when curl's already-satisfied dependencies would keep it. RUN apt-get update \ && apt-get install --yes --no-install-recommends curl ca-certificates libssl3t64 openssl \ && rm -rf /var/lib/apt/lists/* \ && groupadd --gid 10001 knowledgehub \ && useradd --uid 10001 --gid 10001 --no-create-home --shell /usr/sbin/nologin knowledgehub \ && mkdir -p \ /app \ /var/lib/knowledge-hub/data \ /var/lib/knowledge-hub/attachments \ /var/lib/knowledge-hub/imports \ /var/lib/knowledge-hub/exports \ /var/lib/knowledge-hub/backups \ /var/lib/knowledge-hub/keys \ && chown -R 10001:10001 /app /var/lib/knowledge-hub WORKDIR /app COPY --from=backend-build --chown=10001:10001 /app/publish ./ USER 10001:10001 EXPOSE 8080 HEALTHCHECK --interval=15s --timeout=5s --start-period=30s --retries=10 \ CMD ["curl", "--fail", "--silent", "--show-error", "http://127.0.0.1:8080/health/live"] ENTRYPOINT ["dotnet", "ItWorx.KnowledgeHub.Api.dll"]