services: db: image: postgres:18-alpine restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-qrcode} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD fehlt — bitte .env aus .env.example anlegen} POSTGRES_DB: ${POSTGRES_DB:-qrcode} volumes: # Ab PostgreSQL 18 liegt das Datenverzeichnis in einem Unterordner mit # Versionsnummer — der Mountpunkt ist deshalb /var/lib/postgresql und # nicht mehr /var/lib/postgresql/data. - db-data:/var/lib/postgresql healthcheck: # Die App startet erst, wenn die Datenbank wirklich Anfragen annimmt. test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-qrcode} -d ${POSTGRES_DB:-qrcode}"] interval: 5s timeout: 5s retries: 12 start_period: 10s app: build: context: . restart: unless-stopped depends_on: db: condition: service_healthy environment: # Achtung beim Ergänzen: Compose liest die .env nur, um Platzhalter wie # ${BASE_URL} zu ersetzen. In den Container gelangt ausschließlich, was # hier aufgeführt ist — eine neue Variable in der .env allein bleibt # wirkungslos. # # Öffentliche Adresse der App — landet in jedem dynamischen QR-Code. BASE_URL: ${BASE_URL:-http://localhost:3000} DATABASE_URL: ${DATABASE_URL} # Anmeldung mit Benutzern, Gruppen und Rollen. AUTH_ENABLED: ${AUTH_ENABLED:-false} MAX_UPLOAD_MB: ${MAX_UPLOAD_MB:-10} ports: # Direktes Port-Mapping, bewusst ohne Reverse Proxy. - "${APP_PORT:-3000}:3000" volumes: db-data: