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: # Öffentliche Adresse der App — landet in jedem dynamischen QR-Code. BASE_URL: ${BASE_URL:-http://localhost:3000} DATABASE_URL: ${DATABASE_URL} ports: # Direktes Port-Mapping, bewusst ohne Reverse Proxy. - "${APP_PORT:-3000}:3000" volumes: db-data: