From 7e99bbd54c8adbb5b5f3388e546d81c1434ca6d9 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sat, 27 Jun 2026 16:13:12 +0100 Subject: [PATCH] docker: add Dockerfile.runtime / .blogs / .api for ASP.NET images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three new Dockerfiles, each producing a minimal runtime image based on mcr.microsoft.com/dotnet/aspnet:10.0: - Dockerfile.runtime : Yavsc.Org (port 5000 HTTP) - Dockerfile.runtime.blogs : Yavsc.Blogs (port 5004 HTTP) - Dockerfile.runtime.api : Yavsc.Api (port 5002 HTTP) Each one: 1. COPY --from=pazof/yavsc-build-env:debian12-dotnet10-android36-v1 /app/publish// — i.e. the artifacts produced by the publish step added in the previous commit. 2. Injects appsettings-org.json via BuildKit secret mount (--mount=type=secret,id=yavsc_appsettings). The secret never lands in a layer — BuildKit copies it into /app and discards the mount. 3. Sets ASPNETCORE_URLS to the project's HTTP port and exposes it. 4. Adds a HEALTHCHECK that pings the root URL. HTTPS (ports 5001, 5003, 5005) is intentionally NOT exposed in the Dockerfile: enabling it requires mounting /etc/letsencrypt (typically via docker-compose) and configuring Kestrel:Certificates in appsettings-org.json. The compose file in the next commit documents the volume mount pattern. --- Dockerfile.runtime | 59 ++++++++++++++++++++++++++++++++++++++++ Dockerfile.runtime.api | 33 ++++++++++++++++++++++ Dockerfile.runtime.blogs | 34 +++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 Dockerfile.runtime create mode 100644 Dockerfile.runtime.api create mode 100644 Dockerfile.runtime.blogs diff --git a/Dockerfile.runtime b/Dockerfile.runtime new file mode 100644 index 00000000..84f743d8 --- /dev/null +++ b/Dockerfile.runtime @@ -0,0 +1,59 @@ +# Image runtime pour Yavsc.Org (front web utilisateur-facing). +# +# Construit par-dessus l'image de build (qui produit /app/publish/Yavsc.Org) +# et copie l'artefact publié dans une image ASP.NET minimale. +# +# Le appsettings-org.json n'est PAS commit (le repo n'expose pas la +# configuration de prod). Il est injecté au build via un BuildKit secret +# mount, ex: +# +# docker build \ +# --secret id=yavsc_appsettings,src=./appsettings-org.json \ +# -f Dockerfile.runtime \ +# -t yavsc-org:dev . +# +# En production le secret peut être fourni via le store CI (GitHub Actions +# secrets, etc.). Le chemin du fichier monté (/run/secrets/yavsc_appsettings) +# ne se retrouve PAS dans l'image finale : on le copie dans /app avant +# qu'il ne soit effacé du cache BuildKit. +# +# Pour activer HTTPS en production, monter un volume de certificats +# Letsencrypt (typiquement /etc/letsencrypt) en lecture : +# +# volumes: +# - /etc/letsencrypt:/etc/letsencrypt:ro +# +# et renseigner ASPNETCORE_URLS + Kestrel:Certificates dans la config. +# En dev local, on n'expose que HTTP (5000). + +# syntax=docker/dockerfile:1.7 +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime + +WORKDIR /app + +# 1. Copier l'artefact publié depuis l'image de build. On ne référence +# pas pazof/yavsc-build-env:latest directement — le contexte de +# build (compose ou CI) contrôle quelle image source est utilisée. +ARG BUILD_ENV_IMAGE=pazof/yavsc-build-env:debian12-dotnet10-android36-v1 +COPY --from=${BUILD_ENV_IMAGE} /app/publish/Yavsc.Org/ ./ + +# 2. appsettings-org.json : injecté via BuildKit secret mount. +# Le /run/secrets/... est un tmpfs éphémère, on copie dans /app puis +# le secret disparaît avec le cache BuildKit. +RUN --mount=type=secret,id=yavsc_appsettings,dst=/run/secrets/yavsc_appsettings \ + cp /run/secrets/yavsc_appsettings /app/appsettings-org.json \ + && chmod 0644 /app/appsettings-org.json + +# 3. ASPNETCORE_ENVIRONMENT=Production par défaut ; surchargeable au run. +ENV ASPNETCORE_ENVIRONMENT=Production +ENV ASPNETCORE_URLS=http://+:5000 + +EXPOSE 5000 + +# Healthcheck simple : on ping /. ASP.NET répond 200 sur la racine en +# mode production ; si le binding échoue, le conteneur est marqué +# unhealthy et docker-compose peut le redémarrer. +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ + CMD wget --quiet --spider http://localhost:5000/ || exit 1 + +ENTRYPOINT ["dotnet", "Yavsc.Org.dll"] diff --git a/Dockerfile.runtime.api b/Dockerfile.runtime.api new file mode 100644 index 00000000..2090730b --- /dev/null +++ b/Dockerfile.runtime.api @@ -0,0 +1,33 @@ +# Image runtime pour Yavsc.Api (API REST JSON principale, consommée +# par les clients headless : PostIt, intégrations tierces, etc.). +# +# Cf. Dockerfile.runtime pour le pattern appsettings-org.json via +# BuildKit secret mount, et le montage optionnel /etc/letsencrypt +# pour HTTPS en production. +# +# docker build \ +# --secret id=yavsc_appsettings,src=./appsettings-org.json \ +# -f Dockerfile.runtime.api \ +# -t yavsc-api:dev . + +# syntax=docker/dockerfile:1.7 +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime + +WORKDIR /app + +ARG BUILD_ENV_IMAGE=pazof/yavsc-build-env:debian12-dotnet10-android36-v1 +COPY --from=${BUILD_ENV_IMAGE} /app/publish/Yavsc.Api/ ./ + +RUN --mount=type=secret,id=yavsc_appsettings,dst=/run/secrets/yavsc_appsettings \ + cp /run/secrets/yavsc_appsettings /app/appsettings-org.json \ + && chmod 0644 /app/appsettings-org.json + +ENV ASPNETCORE_ENVIRONMENT=Production +ENV ASPNETCORE_URLS=http://+:5002 + +EXPOSE 5002 + +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ + CMD wget --quiet --spider http://localhost:5002/ || exit 1 + +ENTRYPOINT ["dotnet", "Yavsc.Api.dll"] diff --git a/Dockerfile.runtime.blogs b/Dockerfile.runtime.blogs new file mode 100644 index 00000000..b3827b5c --- /dev/null +++ b/Dockerfile.runtime.blogs @@ -0,0 +1,34 @@ +# Image runtime pour Yavsc.Blogs (backend API headless des blogs, +# destiné à être déployé sur un sous-domaine dédié en production — +# cf. doc/architecture/decoupage-organisation.md). +# +# Cf. Dockerfile.runtime pour le pattern appsettings-org.json via +# BuildKit secret mount, et le montage optionnel /etc/letsencrypt +# pour HTTPS en production. +# +# docker build \ +# --secret id=yavsc_appsettings,src=./appsettings-org.json \ +# -f Dockerfile.runtime.blogs \ +# -t yavsc-blogs:dev . + +# syntax=docker/dockerfile:1.7 +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime + +WORKDIR /app + +ARG BUILD_ENV_IMAGE=pazof/yavsc-build-env:debian12-dotnet10-android36-v1 +COPY --from=${BUILD_ENV_IMAGE} /app/publish/Yavsc.Blogs/ ./ + +RUN --mount=type=secret,id=yavsc_appsettings,dst=/run/secrets/yavsc_appsettings \ + cp /run/secrets/yavsc_appsettings /app/appsettings-org.json \ + && chmod 0644 /app/appsettings-org.json + +ENV ASPNETCORE_ENVIRONMENT=Production +ENV ASPNETCORE_URLS=http://+:5004 + +EXPOSE 5004 + +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ + CMD wget --quiet --spider http://localhost:5004/ || exit 1 + +ENTRYPOINT ["dotnet", "Yavsc.Blogs.dll"]