version: "3.9" networks: frontend: external: true # redis + postgres-logistics live here; routes_api joins it purely to reach redis. logistics: external: true services: routes_api: build: context: . dockerfile: Dockerfile image: routes-api:latest container_name: routes_api restart: unless-stopped environment: - UVICORN_WORKERS=2 # Redis as discrete parts, NOT a hand-built REDIS_URL: the password contains # reserved characters and inlining it produced redis://:pa@ss@routes_redis/..., # which resolved to a garbage host and silently fell back to in-memory cache. # app/services/__init__.py percent-encodes these when assembling the URL. # Host is `redis` (its container name) on the logistics network. - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD} # Optional: Set cache TTL in seconds (default: 300 = 5 min, 86400 = 24h) # Uncomment and set in .env file: REDIS_CACHE_TTL_SECONDS=86400 # - REDIS_CACHE_TTL_SECONDS=${REDIS_CACHE_TTL_SECONDS} # Self-hosted Valhalla, source of the road travel-time matrix used for # road-aware stop sequencing. Unset -> sequencing falls back to aerial. - VALHALLA_URL=http://routes_valhalla:8002 # nearledb (read-only) — source for empirical ETA learning - DB_HOST=${DB_HOST} - DB_PORT=${DB_PORT} - DB_NAME=${DB_NAME} - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} labels: - traefik.enable=true - traefik.http.routers.routes_api.rule=Host(`routes.workolik.com`) - traefik.http.routers.routes_api.entrypoints=websecure - traefik.http.routers.routes_api.tls.certresolver=letsencrypt - traefik.http.services.routes_api.loadbalancer.server.port=8002 - traefik.docker.network=frontend volumes: - ./ml_data:/app/ml_data - ./rider_history.pkl:/app/rider_history.pkl - ./rider_active_state.pkl:/app/rider_active_state.pkl - ./delivery_details.csv:/app/delivery_details.csv:ro - ./delivery_corrections.csv:/app/delivery_corrections.csv:ro networks: - frontend - logistics # Road travel-time matrix backend. Replaces the Google Distance Matrix API: # no key, no per-request cost, no element cap, and a real `motorcycle` costing # model instead of car durations. # # Deliberately NOT using tile_urls. This host has 3.8 GB RAM and runs production # alongside it; building the 556 MB South India extract here risks the OOM killer # taking down routes_api/postgres. Instead ./valhalla_tiles holds a pre-clipped # Coimbatore PBF (bbox 76.60,10.70 -> 77.30,11.35, derived from the actual # delivery coordinates in delivery_details.csv, which span only ~19 km). Valhalla # builds from any .pbf it finds in /custom_files. # # To re-clip after an OSM refresh, on the host: # osmium extract -b 76.60,10.70,77.30,11.35 .osm.pbf \ # -o valhalla_tiles/coimbatore.osm.pbf # docker compose up -d --force-recreate valhalla # with force_rebuild=True valhalla: image: ghcr.io/valhalla/valhalla-scripted:latest container_name: routes_valhalla restart: unless-stopped environment: - serve_tiles=True - force_rebuild=False - build_elevation=False # India drives on the left; admin regions are what teach Valhalla that. - build_admins=True - build_time_zones=True # Reuse built tiles on restart instead of rebuilding from the PBF. - use_tiles_ignore_pbf=True # Hard cap so a runaway tile build gets killed instead of the OOM killer # picking off production containers on this 3.8 GB host. mem_limit: 2g volumes: - ./valhalla_tiles:/custom_files # Loopback-only: the API reaches Valhalla over the docker network, so this # is purely for local probing. Valhalla has no auth — do not bind 0.0.0.0. ports: - "127.0.0.1:8002:8002" networks: - frontend