services: db: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: calendar POSTGRES_PASSWORD: calendar POSTGRES_DB: calendar # KEIN Port-Mapping: Die DB ist nur im internen Compose-Netz # erreichbar (App verbindet ueber den Hostnamen "db"). Fuer # lokalen Zugriff bei Bedarf: docker compose exec db psql ... volumes: - pgdata:/var/lib/postgresql/data # Legt den least-privilege-App-User an (nur bei initialer # Volume-Initialisierung; siehe Script fuer Bestands-Volumes). - ./docker/postgres/init:/docker-entrypoint-initdb.d:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U calendar -d calendar"] interval: 5s timeout: 5s retries: 10 # Taeglicher DB-Backup-Service: erstellt um 02:00 Uhr ein # pg_dump-Backup im Named Volume "pgbackups". Aeltere Backups werden # automatisch nach 7 Tagen geloescht (Retention). Die Backups # ueberleben Neustarts des Stacks, da sie im Volume liegen. db-backup: image: prodrigestivill/postgres-backup-local:16-alpine restart: unless-stopped depends_on: db: condition: service_healthy environment: POSTGRES_HOST: db POSTGRES_DB: calendar POSTGRES_USER: calendar POSTGRES_PASSWORD: calendar # Taeglich um 02:00 Uhr (Cron). SCHEDULE: "@daily" # Backups nach 7 Tagen automatisch loeschen. BACKUP_KEEP_DAYS: 7 # Zusaetzlich die letzten 4 Wochensicherungen behalten. BACKUP_KEEP_WEEKS: 4 # Monats-Sicherungen der letzten 3 Monate behalten. BACKUP_KEEP_MONTHS: 3 # Kompression aktivieren (platzsparend). POSTGRES_EXTRA_OPTS: "-Z6" TZ: Europe/Berlin volumes: - pgbackups:/backups app: build: . restart: unless-stopped depends_on: db: condition: service_healthy environment: DATABASE_URL: postgresql://calendar_app:calendar_app@db:5432/calendar?schema=public # KEIN Fallback-Secret: Ohne gesetztes SESSION_SECRET failt die # App hart beim Start (lib/config.ts), statt JWTs mit einem # oeffentlich bekannten Secret zu signieren. SESSION_SECRET: ${SESSION_SECRET:?SESSION_SECRET muss gesetzt sein (z. B. in .env, siehe .env.example)} APP_URL: ${APP_URL:-http://localhost:3000} ALLOW_OPEN_REGISTRATION: ${ALLOW_OPEN_REGISTRATION:-true} # Optional: Admin-Account beim ersten Start anlegen (First-Run). # Nicht-destruktiv: Legt den Admin nur an, wenn noch keiner # existiert. Bestehende User werden niemals geloescht. # Wenn NICHT gesetzt, laeuft das Seed-Script ohne Nebeneffekte durch. SEED_ADMIN_EMAIL: ${SEED_ADMIN_EMAIL:-} SEED_ADMIN_PASSWORD: ${SEED_ADMIN_PASSWORD:-} NODE_ENV: production ports: - "3000:3000" volumes: pgdata: pgbackups: