# syntax=docker/dockerfile:1 # Gebaut wird auf der Architektur des Bauwirts, übersetzt wird für die des # Ziels — `dotnet publish -a` kann das. Ohne diese Trennung liefe der Bau für # arm64 unter Emulation und dauerte ein Vielfaches. FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0 AS build ARG TARGETARCH WORKDIR /src # Erst die Projektdateien, dann wiederherstellen: so bleibt die # Paket-Wiederherstellung in der Ebenenzwischenablage, solange sich keine # Abhängigkeit ändert. Ohne diesen Schritt lädt jeder Bau alles neu. # `--parents` behält die Verzeichnisse bei. **Ein Muster statt einer Liste**, # weil eine Liste bei jedem neuen Projekt vergessen wird — und dann scheitert # erst der Bau im Container, nicht der auf dem Arbeitsrechner. COPY --parents src/*/*.csproj ./ RUN dotnet restore src/Halo.Api/Halo.Api.csproj -a $TARGETARCH COPY . . RUN dotnet publish src/Halo.Api/Halo.Api.csproj -a $TARGETARCH -c Release -o /app --no-restore FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime # **Die Verzeichnisse müssen hier angelegt werden, nicht erst beim Start.** # Docker legt den Einhängepunkt eines frischen benannten Volumes sonst als # `root` an und übernimmt für ein leeres Volume die Rechte aus dem Image — # gibt es das Verzeichnis im Image nicht, erbt es `root:root`, und der erste # Start scheitert für jeden, der kein Bind Mount benutzt. RUN mkdir -p /config /cache /transcode && chown -R 1000:1000 /config /cache /transcode # **Kein root.** Die Kennung 1000 ist die des ersten Benutzers auf fast jedem # Linux und auf den üblichen NAS-Geräten — wessen Dateien anders gehören, setzt # in der Compose-Datei `user: ":"`. Das ist Docker-Bordmittel und # braucht weder ein Startskript noch root im Container. USER 1000:1000 ENV HALO_DATA=/config \ HALO_CACHE=/cache \ HALO_TRANSCODE=/transcode \ ASPNETCORE_URLS=http://+:8080 \ DOTNET_gcServer=0 WORKDIR /app COPY --from=build /app . EXPOSE 8080 VOLUME ["/config", "/cache", "/transcode"] ENTRYPOINT ["dotnet", "Halo.Api.dll"]