# 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.
COPY src/Halo.Api/Halo.Api.csproj src/Halo.Api/
COPY src/Halo.Core/Halo.Core.csproj src/Halo.Core/
COPY src/Halo.Data/Halo.Data.csproj src/Halo.Data/
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: "<uid>:<gid>"`. 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"]
