Add Docker setup and fix proxy config for containerized deployment

- Program.cs: remove UseHsts/UseHttpsRedirection (NPM terminates TLS,
  would loop behind the proxy, plan.md AE-4), add UseForwardedHeaders
  with emptied known networks/proxies. Uses KnownIPNetworks (net10).
- Dockerfile: SDK build stage, chiseled aspnet runtime on port 8080.
- .dockerignore: keep build output, git and docs out of the image.
- compose.yaml: temporary test setup (builds from source, exposes
  5000:8080) for the first run on Unraid without NPM or registry.
- .gitignore: exclude .idea/ (Rider project files).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tleiningerandClaude Opus 4.8 committed 2026-09-20 23:00:47 +02:00
1 parent 2298051bf4
commit 95946a4349
5 files changed
+87 -5

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
# Build-Ausgaben (werden im Container frisch erzeugt)
**/bin/
**/obj/
**/out/
# IDE- und Tooling-Kram
.vs/
.idea/
.vscode/
# Versionskontrolle und Doku, im Image nicht benoetigt
.git/
.gitea/
.gitignore
.gitattributes
docs/
*.md
# Docker-Dateien selbst
Dockerfile
.dockerignore
compose.yaml
+2 -1
View File
@@ -2,4 +2,5 @@ bin/
obj/ obj/
/packages/ /packages/
riderModule.iml riderModule.iml
/_ReSharper.Caches/ /_ReSharper.Caches/
.idea/
+22
View File
@@ -0,0 +1,22 @@
# syntax=docker/dockerfile:1
# --- Build-Stufe: SDK-Image kompiliert und published die App ---
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
# Zuerst nur die csproj kopieren und restoren, damit der NuGet-Restore-Layer
# gecacht bleibt, solange sich die Abhaengigkeiten nicht aendern.
COPY Elternbeirat.Web/Elternbeirat.Web.csproj Elternbeirat.Web/
RUN dotnet restore Elternbeirat.Web/Elternbeirat.Web.csproj
# Dann der restliche Quellcode.
COPY . .
RUN dotnet publish Elternbeirat.Web/Elternbeirat.Web.csproj -c Release -o /app
# --- Runtime-Stufe: schlankes chiseled-Image, laeuft als non-root (UID 1654),
# hoert auf Port 8080, enthaelt keine Shell (kein HEALTHCHECK mit curl/sh). ---
FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble-chiseled AS runtime
WORKDIR /app
COPY --from=build /app .
EXPOSE 8080
ENTRYPOINT ["dotnet", "Elternbeirat.Web.dll"]
+17 -4
View File
@@ -1,4 +1,5 @@
using Elternbeirat.Web.Components; using Elternbeirat.Web.Components;
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@@ -7,20 +8,32 @@ builder.Services.AddRazorComponents();
var app = builder.Build(); var app = builder.Build();
// NPM terminiert TLS und ist der einzige Weg zum Container (kein Port-Mapping
// im Produktivbetrieb, siehe plan.md AE-4). Ohne UseForwardedHeaders sieht die
// App jede Anfrage als HTTP und mit der Proxy-IP statt der Client-IP.
// KnownNetworks/KnownProxies bewusst geleert, weil ausschliesslich NPM den
// Container erreicht.
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
KnownIPNetworks = { },
KnownProxies = { }
});
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment()) if (!app.Environment.IsDevelopment())
{ {
app.UseExceptionHandler("/Error", createScopeForErrors: true); app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. // Kein UseHsts() und kein UseHttpsRedirection(): NPM setzt HSTS und
app.UseHsts(); // terminiert TLS. Beides hier wuerde hinter dem Proxy eine
// Redirect-Schleife erzeugen (plan.md AE-4).
} }
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true); app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
app.UseHttpsRedirection();
app.UseAntiforgery(); app.UseAntiforgery();
app.MapStaticAssets(); app.MapStaticAssets();
app.MapRazorComponents<App>(); app.MapRazorComponents<App>();
app.Run(); app.Run();
+24
View File
@@ -0,0 +1,24 @@
# TEST-Setup fuer den ersten Lauf auf Unraid (ohne NPM, ohne Registry).
#
# Weicht bewusst vom Produktiv-Setup in plan.md Abschnitt 8 ab:
# - Das Image wird hier direkt aus dem Quellcode gebaut (build:), statt aus
# der Gitea-Registry gezogen. Spart Registry + Token fuer den ersten Test.
# - Es gibt ein Port-Mapping (5000 aussen -> 8080 innen), damit die App im
# lokalen Netz unter http://<unraid>:5000 erreichbar ist. Im Produktiv-
# betrieb entfaellt das Mapping; dort ist nur NPM der Weg zum Container.
#
# Sobald NPM steht, wird diese Datei durch das Produktiv-compose ersetzt.
services:
eb-web:
build:
context: .
dockerfile: Dockerfile
image: elternbeirat-web:test
container_name: eb-web
restart: unless-stopped
environment:
ASPNETCORE_URLS: http://+:8080
TZ: Europe/Berlin
ports:
- "5000:8080" # TEST-Zugang, im Produktivbetrieb entfernen