- Mehrstufige Dockerfiles je Dienst mit Stufen für Entwicklung und Betrieb, beide Images laufen als unprivilegierter Benutzer - Backend-Entrypoint wartet auf die Datenbank, migriert und seedt nur bei leerem Kategoriebaum (neues Flag --if-empty) - docker-compose.yml mit Netz-Trennung, Healthchecks und benannten Volumes; die Datenbank ist ausschließlich im internen Netz erreichbar - nginx liefert das Bundle aus und reicht /api weiter; index.html ungecacht, gehashte Assets ein Jahr - Gitea-Workflows: ci.yml für Lint, Tests und Bundle-Bau, build.yml für die Images nach linux/amd64 ohne Deploy-Schritt - docs/runner.md und docs/deployment.md, .dockerignore je Dienst Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
80 lines
2.7 KiB
Docker
80 lines
2.7 KiB
Docker
# syntax=docker/dockerfile:1.7
|
||
#
|
||
# Backend-Image für moneyfy. Mehrstufig, damit im Endbild weder Build-Werkzeuge
|
||
# noch Entwicklungsabhängigkeiten landen.
|
||
|
||
# --- Abhängigkeiten -----------------------------------------------------------
|
||
FROM python:3.12-slim-bookworm AS deps
|
||
|
||
# uv installiert die Abhängigkeiten deutlich schneller als pip.
|
||
COPY --from=ghcr.io/astral-sh/uv:0.5.11 /uv /bin/uv
|
||
|
||
ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
||
PYTHONDONTWRITEBYTECODE=1 \
|
||
UV_LINK_MODE=copy
|
||
|
||
WORKDIR /app
|
||
|
||
# Nur die Abhängigkeitsdeklaration kopieren – die Schicht bleibt gültig,
|
||
# solange sich pyproject.toml nicht ändert.
|
||
COPY pyproject.toml ./
|
||
RUN /bin/uv pip install --system --no-cache -r pyproject.toml
|
||
|
||
# --- Laufzeitbasis ------------------------------------------------------------
|
||
FROM python:3.12-slim-bookworm AS runtime
|
||
|
||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||
PYTHONUNBUFFERED=1 \
|
||
PYTHONPATH=/app \
|
||
TZ=Europe/Berlin \
|
||
LOGO_STORAGE_DIR=/data/logos
|
||
|
||
# tzdata wird für Europe/Berlin gebraucht, curl für den Healthcheck.
|
||
RUN apt-get update \
|
||
&& apt-get install -y --no-install-recommends tzdata curl \
|
||
&& rm -rf /var/lib/apt/lists/* \
|
||
&& groupadd --system --gid 10001 moneyfy \
|
||
&& useradd --system --uid 10001 --gid moneyfy --create-home --home-dir /home/moneyfy moneyfy
|
||
|
||
COPY --from=deps /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
|
||
COPY --from=deps /usr/local/bin /usr/local/bin
|
||
|
||
WORKDIR /app
|
||
|
||
# --- Entwicklung --------------------------------------------------------------
|
||
# Wird von docker-compose.override.yml genutzt; der Quellcode kommt per Volume.
|
||
FROM runtime AS development
|
||
|
||
COPY --from=ghcr.io/astral-sh/uv:0.5.11 /uv /usr/local/bin/uv
|
||
COPY pyproject.toml ./
|
||
RUN uv pip install --system --no-cache -r pyproject.toml --extra dev
|
||
|
||
COPY --chown=moneyfy:moneyfy . .
|
||
RUN mkdir -p /data/logos && chown -R moneyfy:moneyfy /data
|
||
|
||
USER moneyfy
|
||
EXPOSE 8000
|
||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
||
|
||
# --- Produktion ---------------------------------------------------------------
|
||
FROM runtime AS production
|
||
|
||
COPY --chown=moneyfy:moneyfy alembic.ini pyproject.toml ./
|
||
COPY --chown=moneyfy:moneyfy alembic ./alembic
|
||
COPY --chown=moneyfy:moneyfy app ./app
|
||
COPY --chown=moneyfy:moneyfy docker/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||
|
||
RUN chmod +x /usr/local/bin/entrypoint.sh \
|
||
&& mkdir -p /data/logos \
|
||
&& chown -R moneyfy:moneyfy /data
|
||
|
||
USER moneyfy
|
||
EXPOSE 8000
|
||
VOLUME ["/data"]
|
||
|
||
HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \
|
||
CMD curl -fsS http://127.0.0.1:8000/api/health || exit 1
|
||
|
||
ENTRYPOINT ["entrypoint.sh"]
|
||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--proxy-headers", "--forwarded-allow-ips", "*"]
|