Files
kleiderboerse/Dockerfile
T
StefanandClaude Fable 5 33c728411f X-Forwarded-For nur noch dem Proxy glauben, Durchsicht vom 14.09. notiert
Das CMD startete uvicorn mit --forwarded-allow-ips "*": jeder, der den
Container-Port direkt erreicht, konnte die Absender-IP frei erfinden und
bekam pro erfundener IP einen frischen Rate-Limit-Zaehler - und die
Limits sind das Einzige vor dem frei zugaenglichen Reservieren-Endpunkt.
Zusaetzlich liess sich so die HTTPS-Erkennung fuers Sitzungs-Cookie
faelschen.

Jetzt liest uvicorn die Grenze aus FORWARDED_ALLOW_IPS (ohne Wert: nur
127.0.0.1, also keinem externen Absender trauen). docker-compose.betrieb.yml
reicht die Variable mit Erklaerung durch; das README beschreibt, welche
Adresse hineingehoert und dass der Port nur fuer den Proxy erreichbar
sein darf. Wird die Variable nicht gesetzt, teilen sich alle Besucher
die Zaehler ueber die Proxy-IP - das kleinere Uebel.

Plan-Verbesserungen.md: Ergebnis der erneuten Durchsicht vom 14.09.2026
ergaenzt (GZip/Cache/Sicherung vom 13.09. nachgeprueft und fuer gut
befunden; drei P3-Funde: oeffentlicher 500er ueber ?limit=abc, nicht
atomares Reservieren, 500 statt Fehlermeldung in Betreiber-Formularen).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-14 17:19:12 +02:00

80 lines
3.3 KiB
Docker

# --------------------------------------------------------------- CSS ---
# Tailwind über die Standalone-Binärdatei - kein Node.js, kein npm. Das
# Ergebnis ist eine einzige style.css; die Binärdatei bleibt in dieser
# Stufe und landet nicht im fertigen Image.
FROM debian:bookworm-slim AS css
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
ARG TAILWIND_VERSION=v3.4.17
RUN curl -sSLo /usr/local/bin/tailwindcss \
"https://github.com/tailwindlabs/tailwindcss/releases/download/${TAILWIND_VERSION}/tailwindcss-linux-x64" \
&& chmod +x /usr/local/bin/tailwindcss
COPY tailwind.config.js tailwind-input.css ./
COPY app/templates ./app/templates
RUN tailwindcss -c tailwind.config.js -i tailwind-input.css -o /build/style.css --minify
# ----------------------------------------------------------- Anwendung ---
FROM python:3.11-slim
# libheif wird von pillow-heif mitgeliefert; hier nur die Laufzeit-Bibliotheken,
# die Pillow für JPEG/PNG/WebP braucht.
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY alembic.ini ./
COPY alembic/ ./alembic/
COPY app/ ./app/
COPY --from=css /build/style.css ./app/static/style.css
COPY docker-entrypoint.sh /usr/local/bin/kleiderboerse-entrypoint.sh
RUN chmod +x /usr/local/bin/kleiderboerse-entrypoint.sh
# Datenbank und Bilder liegen in Volumes, ausserhalb des Codes.
ENV DATABASE_PATH=/data/kleiderboerse.sqlite \
UPLOAD_PATH=/uploads \
PYTHONUNBUFFERED=1
# Versionsangabe für die Fusszeile. Die CI reicht Tag und Commit durch;
# lokal bleiben beide leer und es erscheint der Build-Zeitpunkt - der
# ändert sich bei jedem Neubau und zeigt so, ob der neue Stand läuft.
ARG APP_VERSION=""
ARG APP_REVISION=""
ENV APP_VERSION="$APP_VERSION" \
APP_REVISION="$APP_REVISION"
# Nicht als root laufen. Die beiden Verzeichnisse gehören dem Dienstbenutzer,
# der Code dagegen root - so kann der Webdienst seinen eigenen Code nicht
# überschreiben.
RUN date -u '+%d.%m.%Y %H:%M UTC' > /app/build.txt
RUN useradd --system --create-home --shell /usr/sbin/nologin kleider \
&& mkdir -p /data /uploads \
&& chown kleider:kleider /data /uploads
USER kleider
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsS http://localhost:8000/health || exit 1
ENTRYPOINT ["kleiderboerse-entrypoint.sh"]
# --proxy-headers: hinter einem Reverse-Proxy stünde sonst dessen IP in
# jedem Rate-Limit, und ein einzelner Besucher sperrte alle anderen aus.
# Ausserdem erkennt die App darüber, ob der Browser per HTTPS verbunden ist.
#
# WEM die X-Forwarded-*-Kopfzeilen geglaubt werden, steuert
# FORWARDED_ALLOW_IPS - uvicorn liest die Variable selbst aus der Umgebung
# (ohne Wert: nur 127.0.0.1). Früher stand hier "--forwarded-allow-ips *":
# damit durfte jeder, der den Port direkt erreicht, die Absender-IP frei
# erfinden - pro erfundener IP ein frischer Rate-Limit-Zähler, und die
# Limits sind das Einzige vor dem Reservieren-Endpunkt. Im Betrieb die
# Adresse des Proxys eintragen (siehe docker-compose.betrieb.yml).
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", \
"--proxy-headers"]