services: # Database: PostgreSQL + PostGIS # قاعدة البيانات: تخزين البيانات الجغرافية db: image: postgis/postgis:15-3.3 container_name: map-db platform: linux/amd64 # Ensure compatibility on Mac Silicon environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./infrastructure/osm-data:/infrastructure/osm-data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 # Cache: Redis # التخزين المؤقت: تخزين البيانات السريعة ومواقع السائقين اللحظية redis: image: redis:7-alpine container_name: map-redis platform: linux/amd64 ports: - "6381:6379" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 # Routing Engine: GraphHopper routing: build: context: . dockerfile: ./infrastructure/docker/graphhopper/Dockerfile container_name: map-routing platform: linux/amd64 ports: - "8989:8080" environment: # 7.8GB إجمالي على السيرفر. باقي الحاويات ~1.3GB + النظام ~0.5GB. # Xmx5g كان ينتج RSS ~6GB فيصطدم بالسقف ويُقتل بالـ OOM لحظة عودة باقي # الحاويات — رغم أن البناء نفسه ينجح حين تكون موقوفة. 4g تترك هامشاً حقيقياً. - JAVA_OPTS=-Xmx4g -Xms1g deploy: resources: limits: memory: 6g volumes: - ./infrastructure/osm-data:/data - graphhopper-srtm-cache:/data/srtm-cache - ./infrastructure/docker/graphhopper/config.yml:/graphhopper/config.yml command: ["server", "/graphhopper/config.yml"] healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"] interval: 60s timeout: 30s retries: 5 start_period: 1200s depends_on: - db # Tile Server: Tileserver-GL # خادم الخرائط: عرض طبقات الخريطة للمتصفح وتطبيق الموبايل #tileserver: # image: maptiler/tileserver-gl:latest # container_name: map-tileserver # platform: linux/amd64 # ports: # - "8080:80" # volumes: # - ./infrastructure/osm-data:/data # - ./infrastructure/docker/tileserver:/config # command: ["-c", "/config/config.json"] # healthcheck: # test: ["CMD", "curl", "-f", "http://localhost/"] # interval: 30s # timeout: 10s # retries: 3 # Backend API: NestJS # البرمجية الخلفية: إدارة الطلبات والبيانات اللحظية api: build: context: . dockerfile: ./infrastructure/docker/api/Dockerfile container_name: map-api platform: linux/amd64 ports: - "3200:3200" environment: - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} - REDIS_URL=redis://redis:6379 - API_PORT=${API_PORT} - MAP_API_KEY=${MAP_API_KEY} - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID} - LOCATION_SERVER_URL=${LOCATION_SERVER_URL} - LOCATION_SERVER_API_KEY=${LOCATION_SERVER_API_KEY} - GRAPH_HOPPER_URL=${GRAPH_HOPPER_URL} - TILE_SERVER_URL=${TILE_SERVER_URL} - FIREBASE_SERVICE_ACCOUNT_PATH=${FIREBASE_SERVICE_ACCOUNT_PATH} - PAYMOB_API_KEY=${PAYMOB_API_KEY} - PAYMOB_HMAC_SECRET=${PAYMOB_HMAC_SECRET} - PAYMOB_INTEGRATION_ID=${PAYMOB_INTEGRATION_ID} - PAYMOB_IFRAME_ID=${PAYMOB_IFRAME_ID} - BINANCE_PAY_API_KEY=${BINANCE_PAY_API_KEY} - BINANCE_PAY_SECRET_KEY=${BINANCE_PAY_SECRET_KEY} - BINANCE_PAY_MERCHANT_ID=${BINANCE_PAY_MERCHANT_ID} - GEMINI_API_KEY=${GEMINI_API_KEY} volumes: - .:/data - ./infrastructure/secrets:/secrets:ro depends_on: db: condition: service_healthy redis: condition: service_healthy routing: condition: service_healthy # Tile Server: Martin (Vector Tiles from PostGIS) # خادم الخرائط: توليد مربعات الخرائط مباشرة من قاعدة البيانات martin: image: maplibre/martin:latest container_name: map-martin platform: linux/amd64 ports: - "3202:3000" environment: - WATCH_DB=true command: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} depends_on: db: condition: service_healthy # Valhalla Routing Tile Builder (on-device offline routing package) # بانِ حزمة التوجيه المحلية: يبني غراف طرق الأردن الحقيقي مع ارتفاعات SRTM # ليعمل التوجيه داخل التطبيق التكتيكي بدون إنترنت بنفس دقة السيرفر. # تشغيل: docker compose --profile tiles run --rm valhalla-tiles valhalla-tiles: image: ghcr.io/valhalla/valhalla:latest container_name: map-valhalla-tiles platform: linux/amd64 profiles: - tiles volumes: - ./infrastructure/osm-data:/data - ./infrastructure/scripts/build-valhalla-tiles.sh:/build-valhalla-tiles.sh:ro entrypoint: ["bash", "/build-valhalla-tiles.sh"] # OSM Import Tool: osm2pgsql # أداة استيراد البيانات: لاستيراد ملف OSM إلى قاعدة البيانات osm-import: image: iboates/osm2pgsql:latest container_name: map-import platform: linux/amd64 volumes: - ./infrastructure/osm-data:/data environment: - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} - PGPASSWORD=${POSTGRES_PASSWORD} command: ["osm2pgsql", "--create", "--slim", "--cache", "1000", "--database", "${POSTGRES_DB}", "--host", "db", "--user", "${POSTGRES_USER}", "/data/region.osm.pbf"] depends_on: db: condition: service_healthy profiles: - import # Run only with --profile import # Web Frontend: React (Map Dashboard) web: build: context: . dockerfile: ./infrastructure/docker/web/Dockerfile container_name: map-web platform: linux/amd64 ports: - "3201:5173" environment: - VITE_API_KEY=${MAP_API_KEY} - VITE_API_URL=/api volumes: - ./apps/web/public:/app/public - ./apps/web/src:/app/src depends_on: - api - martin # Commercial Dashboard: Vanilla HTML/CSS/JS (High Performance) dashboard: build: context: . dockerfile: ./infrastructure/docker/dashboard/Dockerfile container_name: map-dashboard platform: linux/amd64 ports: - "3204:80" volumes: - ./apps/dashboard:/usr/share/nginx/html:ro depends_on: - api volumes: postgres_data: redis_data: graphhopper-srtm-cache: