Files
eveAI/documentation/migratie_startup_en_builds.md
Josako 16ce59ae98 - Introduce cache busting (to circumvent aggressive caching on iOS - but ideal in other contexts as well)
- Change the build process to allow cache busting
- Optimisations to the build process
- Several improvements of UI geared towards mobile experience
-
2025-09-25 17:28:01 +02:00

5.9 KiB

Migratieplan: Standaardisatie van Startup Processen en Docker Builds

Dit document beschrijft de migratie-afspraken rond het opstarten van onze applicaties, inclusief het gebruik van een generiek startscript, het inzetten van tini als entrypoint, en de overstap naar een shared base build structuur.

Doel: standaardisatie, betere betrouwbaarheid in Kubernetes, en snellere builds.


1. Generiek startscript (scripts/start.sh)

Doel

  • Eén startscript voor alle rollen: web, worker, beat.
  • Gedrag wordt bepaald via environment variables (ROLE=web|worker|beat).
  • Geen “magische” verschillen meer tussen Podman en Kubernetes.

Voorbeeld

#!/usr/bin/env bash
set -euo pipefail

ROLE="${ROLE:-web}"

case "$ROLE" in
  web)
    exec gunicorn -w "${WORKERS:-1}" -k "${WORKER_CLASS:-gevent}"       -b "0.0.0.0:${PORT:-8080}" --worker-connections "${WORKER_CONN:-100}"       --access-logfile - --error-logfile - --log-level "${LOGLEVEL:-info}"       scripts.run_eveai_app:app
    ;;

  worker)
    exec celery -A scripts.run_eveai_workers worker       --loglevel="${CELERY_LOGLEVEL:-INFO}"       --concurrency="${CELERY_CONCURRENCY:-2}"       --max-tasks-per-child="${CELERY_MAX_TASKS_PER_CHILD:-1000}"       --prefetch-multiplier="${CELERY_PREFETCH:-1}" -O fair
    ;;

  beat)
    exec celery -A scripts.run_eveai_workers beat       --loglevel="${CELERY_LOGLEVEL:-INFO}"
    ;;

  *)
    echo "Unknown ROLE=$ROLE" >&2
    exit 1
    ;;
esac

Belangrijk

  • Geen init/migraties meer in het startscript (die draaien we via Jobs/CronJobs).
  • Geen cd, chown, of PYTHONPATH-hacks in startscript → alles naar Dockerfile.
  • Altijd exec gebruiken zodat processen signalen correct ontvangen.

2. Gebruik van tini als ENTRYPOINT

Waarom?

  • In containers draait het eerste proces als PID 1.
  • Zonder init-proces worden signalen niet correct doorgegeven en ontstaan zombieprocessen.
  • tini is een lichtgewicht init die dit oplost.

Implementatie

RUN apt-get update && apt-get install -y --no-install-recommends tini   && rm -rf /var/lib/apt/lists/*

ENTRYPOINT ["/usr/bin/tini","-g","--"]
CMD ["bash","-lc","scripts/start.sh"]
  • -g = stuur signalen naar de hele process group (belangrijk voor Gunicorn en Celery).
  • Hiermee is een apart entrypoint.sh niet meer nodig.

3. Verplaatsen van logica naar Dockerfile

Wat naar de Dockerfile moet

  • WORKDIR /app
  • ENV PYTHONPATH=/app:/app/patched_packages:$PYTHONPATH
  • ENV FLASK_APP=/app/scripts/run_eveai_app.py (alleen nodig voor CLI, niet voor gunicorn)
  • User-aanmaak en permissies:
    ARG UID=10001
    ARG GID=10001
    RUN groupadd -g ${GID} appuser    && useradd  -u ${UID} -g ${GID} -M -d /nonexistent -s /usr/sbin/nologin appuser
    RUN chown -R appuser:appuser /app
    USER appuser
    

Wat niet meer in startscript hoort

  • cd /app
  • export PYTHONPATH=...
  • chown -R ... /logs
  • DB-migraties of cache-invalidatie → deze verhuizen naar Kubernetes Jobs/CronJobs.

4. Kubernetes Jobs & CronJobs

Use cases

  • Jobs → eenmalige taken zoals DB-migraties of cache-invalidatie.
  • CronJobs → geplande taken (bv. nachtelijke opschoningen).

Waarom?

  • Startup scripts blijven lean.
  • Geen race conditions bij meerdere replicas.
  • Flexibel los van deploys uit te voeren.

5. Docker builds: naar een shared base (Optie B)

Nieuwe structuur

repo/
├─ Dockerfile.base
├─ requirements.txt
├─ common/
├─ config/
├─ scripts/
├─ patched_packages/
├─ docker/
│  ├─ eveai_app/Dockerfile
│  ├─ eveai_api/Dockerfile
│  └─ eveai_workers/Dockerfile
└─ compose_dev.yaml

Dockerfile.base

FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1

RUN apt-get update && apt-get install -y --no-install-recommends tini   && rm -rf /var/lib/apt/lists/*

ARG UID=10001
ARG GID=10001
RUN groupadd -g ${GID} appuser  && useradd  -u ${UID} -g ${GID} -M -d /nonexistent -s /usr/sbin/nologin appuser

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY common           /app/common
COPY config           /app/config
COPY scripts          /app/scripts
COPY patched_packages /app/patched_packages

RUN chown -R appuser:appuser /app && chmod +x /app/scripts/start.sh

ENV PYTHONPATH=/app:/app/patched_packages:${PYTHONPATH} ROLE=web PORT=8080

USER appuser
EXPOSE 8080

ENTRYPOINT ["/usr/bin/tini","-g","--"]
CMD ["bash","-lc","scripts/start.sh"]

Service Dockerfiles

docker/eveai_app/Dockerfile

FROM yourorg/eveai-base:py312-v1
WORKDIR /app
COPY eveai_app /app/eveai_app
COPY migrations /app/migrations
COPY content    /app/content
ENV ROLE=web PORT=8080

docker/eveai_api/Dockerfile

FROM yourorg/eveai-base:py312-v1
WORKDIR /app
COPY eveai_api /app/eveai_api
ENV ROLE=web PORT=8080

docker/eveai_workers/Dockerfile

FROM yourorg/eveai-base:py312-v1
WORKDIR /app
COPY eveai_workers /app/eveai_workers
ENV ROLE=worker

6. Workflow afspraken

  1. Startscript is generiek → gedrag via env (ROLE=...).
  2. Geen init-taken meer in startscript → Jobs/CronJobs in k8s.
  3. tini als ENTRYPOINT → correcte signalen en zombie-cleanup.
  4. Dockerfile regelt PYTHONPATH, FLASK_APP, permissies en user.
  5. Base image bevat Python, deps en common code.
  6. Service-images kopiëren enkel hun eigen directories.
  7. Build flow:
    • Base builden/pushen bij gewijzigde deps/common.
    • Services snel erbovenop rebuilden bij code-wijzigingen.

7. Samenvatting

Met deze migratie krijgen we:

  • Eenvoudiger startscript (alleen proceskeuze).
  • Betere betrouwbaarheid bij shutdowns (via tini).
  • Strikte scheiding tussen lifecycle taken en runtime.
  • Snellere builds via shared base image.
  • Uniforme aanpak in zowel Podman/Compose als Kubernetes.