# FlorianNetz — Basis-Compose hinter EXTERNEM Traefik. # # Es gibt bewusst KEINEN eigenen Proxy-/Traefik-Service: Routing/TLS übernimmt # eine separat betriebene Traefik-Instanz, die am externen Netz "${TRAEFIK_NETWORK}" # (Default: traefik) lauscht. Dieses Netz muss bereits existieren: # docker network create traefik # # Geo-Dienste (osrm, nominatim) sind hier mit ihren Laufzeit-Verträgen definiert; # das schwergewichtige Daten-Preprocessing/Volume kommt aus docker-compose.geo.yml # (siehe scripts/prepare-osm-data.sh / infra/geo). # # Start: # docker compose --env-file .env up -d # Lokal ohne Traefik/TLS: # docker compose -f docker-compose.yml -f docker-compose.override.yml up -d services: app: build: context: . dockerfile: Dockerfile depends_on: postgres: condition: service_healthy environment: NODE_ENV: production DATABASE_URL: postgres://${POSTGRES_USER:-floriannetz}:${POSTGRES_PASSWORD:-floriannetz}@postgres:5432/${POSTGRES_DB:-floriannetz} # Forwarded-Header + sichere Cookies hinter Traefik. AUTH_TRUST_HOST: "true" AUTH_URL: https://${APP_HOST} AUTH_SECRET: ${AUTH_SECRET} AUTHENTIK_ISSUER: ${AUTHENTIK_ISSUER} AUTHENTIK_CLIENT_ID: ${AUTHENTIK_CLIENT_ID} AUTHENTIK_CLIENT_SECRET: ${AUTHENTIK_CLIENT_SECRET} OSRM_URL: http://osrm:5000 NOMINATIM_URL: http://nominatim:8080 GEO_HTTP_TIMEOUT_MS: ${GEO_HTTP_TIMEOUT_MS:-4000} HAVERSINE_KMH: ${HAVERSINE_KMH:-50} RUN_SEED: ${RUN_SEED:-false} networks: - traefik - internal healthcheck: test: - CMD-SHELL - "wget -q -O - http://127.0.0.1:3000/api/health | grep -q ok" interval: 30s timeout: 5s retries: 5 start_period: 40s restart: unless-stopped labels: - "traefik.enable=true" - "traefik.docker.network=${TRAEFIK_NETWORK:-traefik}" - "traefik.http.routers.floriannetz.rule=Host(`${APP_HOST}`)" - "traefik.http.routers.floriannetz.entrypoints=websecure" - "traefik.http.routers.floriannetz.tls=true" - "traefik.http.routers.floriannetz.tls.certresolver=${TRAEFIK_CERTRESOLVER:-letsencrypt}" - "traefik.http.services.floriannetz.loadbalancer.server.port=3000" # Security-Header-Middleware (zusätzlich zu next.config.ts; defense-in-depth). - "traefik.http.routers.floriannetz.middlewares=floriannetz-sechdrs" - "traefik.http.middlewares.floriannetz-sechdrs.headers.stsSeconds=63072000" - "traefik.http.middlewares.floriannetz-sechdrs.headers.stsIncludeSubdomains=true" - "traefik.http.middlewares.floriannetz-sechdrs.headers.contentTypeNosniff=true" - "traefik.http.middlewares.floriannetz-sechdrs.headers.frameDeny=true" postgres: image: postgres:16-alpine environment: POSTGRES_USER: ${POSTGRES_USER:-floriannetz} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-floriannetz} POSTGRES_DB: ${POSTGRES_DB:-floriannetz} volumes: - postgres-data:/var/lib/postgresql/data networks: - internal healthcheck: test: - CMD-SHELL - "pg_isready -U ${POSTGRES_USER:-floriannetz} -d ${POSTGRES_DB:-floriannetz}" interval: 10s timeout: 5s retries: 5 start_period: 30s restart: unless-stopped osrm: build: context: . dockerfile: docker/osrm/Dockerfile command: osrm-routed --algorithm mld /data/austria-latest.osrm volumes: - osrm-data:/data networks: - internal expose: - "5000" healthcheck: test: - CMD-SHELL - >- wget -q -O - 'http://localhost:5000/table/v1/driving/15.6229,48.2079;16.3738,48.2082?sources=0' | grep -q '"code":"Ok"' interval: 30s timeout: 5s retries: 5 start_period: 60s restart: unless-stopped nominatim: image: mediagis/nominatim:4.4 environment: PBF_URL: https://download.geofabrik.de/europe/austria-latest.osm.pbf REPLICATION_URL: https://download.geofabrik.de/europe/austria-updates/ IMPORT_STYLE: address NOMINATIM_PASSWORD: ${NOMINATIM_PASSWORD:-nominatim} volumes: - nominatim-data:/var/lib/postgresql/14/main shm_size: 1g networks: - internal expose: - "8080" healthcheck: test: - CMD-SHELL - "wget -q -O - 'http://localhost:8080/status' | grep -q OK" interval: 30s timeout: 5s retries: 5 start_period: 120s restart: unless-stopped volumes: postgres-data: osrm-data: nominatim-data: networks: # Externes, von der separaten Traefik-Instanz verwaltetes Netz. traefik: external: true name: ${TRAEFIK_NETWORK:-traefik} # Internes Netz: Postgres/Geo sind nur app-intern erreichbar, nicht öffentlich. internal: internal: true