# PM — Construction Project Management Platform services: pm-postgres: image: postgres:18 container_name: pm-postgres environment: POSTGRES_DB: pm POSTGRES_USER: pm POSTGRES_PASSWORD: ${PM_DB_PASSWORD:-pm_secret_2026} ports: - "5434:5432" volumes: - pm_postgres_data:/var/lib/postgresql - ./sql/init.sql:/docker-entrypoint-initdb.d/01-init.sql:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U pm -d pm"] interval: 5s timeout: 5s retries: 10 restart: unless-stopped pm-api: build: context: ./backend dockerfile: Dockerfile container_name: pm-api environment: PM_DATABASE_URL: postgresql+asyncpg://postgres:postgres@procurement-postgres:5432/procurement PM_SESSION_SECRET: ${PM_SESSION_SECRET:-12278fc281bd0e22950e76364e1a18cea61fbc6a24604fdd79690a817ec36ac8} PM_ADMIN_USER: ${PM_ADMIN_USER:-admin} PM_ADMIN_PASSWORD: ${PM_ADMIN_PASSWORD:-pm123456} PM_FILES_DIR: /data/files PM_DEV_ROLE_SWITCH: ${PM_DEV_ROLE_SWITCH:-false} # ERP integration (read-only service account) PM_ERP_BASE_URL: http://procurement-api:8000 PM_ERP_CASDOOR_ENDPOINT: http://casdoor:8000 PM_ERP_CASDOOR_CLIENT_ID: ${PM_ERP_CASDOOR_CLIENT_ID:-inventory-app-client} PM_ERP_CASDOOR_CLIENT_SECRET: ${PM_ERP_CASDOOR_CLIENT_SECRET:-inventory-app-secret-2026} PM_ERP_SERVICE_USERNAME: ${PM_ERP_SERVICE_USERNAME:-pm-service} PM_ERP_SERVICE_PASSWORD: ${PM_ERP_SERVICE_PASSWORD:-pm-service-2026} # Casdoor SSO — همان نشست ERP؛ پیش‌فرض لوکال، origin کسدور لوکال است PM_CASDOOR_ISSUER: ${PM_CASDOOR_ISSUER:-http://localhost:8080} volumes: - pm_files:/data/files - ./backend/app:/srv/pm/app depends_on: pm-postgres: condition: service_healthy networks: - default - erp_default restart: unless-stopped pm-frontend: build: context: ./frontend dockerfile: Dockerfile container_name: pm-frontend ports: - "8083:80" depends_on: - pm-api # پنل «مدیریت پروژه» روی همان دامنه ERP زیر مسیر /pm سرو می‌شود — # Traefikِ استک ERP این کانتینر را با قاعده PathPrefix کشف می‌کند labels: - traefik.enable=true - traefik.http.routers.pm.rule=PathPrefix(`/pm`) - traefik.http.routers.pm.entrypoints=web # اولویت بالاتر از روتر Host(`localhost`) فرانت ERP — وگرنه /pm/api # ممکن است به SPA فرانت ERP برسد (POST → 405) - traefik.http.routers.pm.priority=100 - traefik.http.services.pm.loadbalancer.server.port=80 networks: - default - traefik_network restart: unless-stopped volumes: pm_postgres_data: pm_files: networks: default: name: pm_default erp_default: external: true traefik_network: external: true