TorbatYar/docker-compose.yml
Mortezakoohjani e41ecfad4c Sync platform docs, infra, and module services with Accounting integration.
Include Loyalty/Communication/Sports Center backends and registry updates alongside production nginx and compose wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-25 22:35:23 +03:30

393 lines
13 KiB
YAML

# ============================================================
# SuperApp SaaS Platform - Docker Compose
# postgres, redis, keycloak, core-service, identity-access,
# celery-worker, celery-beat, frontend
# ============================================================
services:
postgres:
image: postgres:15-alpine
container_name: superapp_postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "${POSTGRES_PORT:-5432}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./infrastructure/postgres/init-dbs.sql:/docker-entrypoint-initdb.d/02-init-dbs.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
networks:
- superapp_net
redis:
image: redis:7-alpine
container_name: superapp_redis
restart: unless-stopped
ports:
- "${REDIS_PORT:-6379}:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- superapp_net
keycloak:
image: quay.io/keycloak/keycloak:24.0
container_name: superapp_keycloak
restart: unless-stopped
command: start-dev --import-realm --features=token-exchange
environment:
KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN:-admin}
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-admin}
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB}
KC_DB_USERNAME: ${POSTGRES_USER}
KC_DB_PASSWORD: ${POSTGRES_PASSWORD}
KC_HTTP_ENABLED: "true"
KC_HOSTNAME_STRICT: "false"
KC_PROXY: edge
KC_HOSTNAME: ${KEYCLOAK_HOSTNAME:-auth.torbatyar.ir}
KC_HOSTNAME_STRICT_HTTPS: ${KEYCLOAK_HOSTNAME_STRICT_HTTPS:-false}
JAVA_OPTS_KC_HEAP: "-Xms256m -Xmx512m"
ports:
- "8080:8080"
volumes:
- ./infrastructure/keycloak/realm:/opt/keycloak/data/import
- ./infrastructure/keycloak/themes:/opt/keycloak/themes
depends_on:
postgres:
condition: service_healthy
networks:
- superapp_net
core-service:
build:
context: .
dockerfile: backend/core-service/Dockerfile.dev
container_name: superapp_core_service
restart: unless-stopped
env_file:
- .env
ports:
- "8000:8000"
volumes:
- ./backend/core-service:/app
- ./backend/shared-lib:/shared-lib
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
keycloak:
condition: service_started
command: >
sh -c "alembic upgrade 0001_initial &&
alembic stamp head &&
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload"
networks:
- superapp_net
identity-access-service:
build:
context: .
dockerfile: backend/services/identity-access/Dockerfile.dev
container_name: superapp_identity_service
restart: unless-stopped
env_file:
- .env
environment:
DATABASE_URL: ${IDENTITY_DATABASE_URL}
DATABASE_URL_SYNC: ${IDENTITY_DATABASE_URL_SYNC}
IDENTITY_KEYCLOAK_CLIENT_ID: identity-access-service
KEYCLOAK_IDENTITY_CLIENT_SECRET: ${KEYCLOAK_IDENTITY_CLIENT_SECRET:-change-me-identity}
PLATFORM_ADMIN_MOBILES: ${PLATFORM_ADMIN_MOBILES:-}
KEYCLOAK_SERVER_URL: http://keycloak:8080
KEYCLOAK_PUBLIC_URL: ${KEYCLOAK_PUBLIC_URL:-http://localhost:8080}
CORE_SERVICE_URL: ${CORE_SERVICE_URL:-http://core-service:8000}
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000}
ports:
- "8001:8001"
volumes:
- ./backend/services/identity-access:/app
- ./backend/shared-lib:/shared-lib
depends_on:
postgres:
condition: service_healthy
keycloak:
condition: service_started
core-service:
condition: service_started
command: >
sh -c "python scripts/ensure_db.py &&
alembic upgrade 0001_initial &&
alembic stamp head &&
(python scripts/enable_mobile_auth_client.py || true) &&
uvicorn app.main:app --host 0.0.0.0 --port 8001 --reload"
networks:
- superapp_net
accounting-service:
build:
context: .
dockerfile: backend/services/accounting/Dockerfile.dev
container_name: superapp_accounting_service
restart: unless-stopped
env_file:
- .env
environment:
ACCOUNTING_DATABASE_URL: ${ACCOUNTING_DATABASE_URL}
ACCOUNTING_DATABASE_URL_SYNC: ${ACCOUNTING_DATABASE_URL_SYNC}
CORE_SERVICE_URL: ${CORE_SERVICE_URL:-http://core-service:8000}
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000}
AUTH_REQUIRED: ${AUTH_REQUIRED:-true}
KEYCLOAK_SERVER_URL: ${KEYCLOAK_SERVER_URL:-http://keycloak:8080}
KEYCLOAK_PUBLIC_URL: ${KEYCLOAK_PUBLIC_URL:-http://localhost:8080}
KEYCLOAK_REALM: ${KEYCLOAK_REALM:-superapp}
JWT_VERIFY_SIGNATURE: ${JWT_VERIFY_SIGNATURE:-true}
ports:
- "8002:8002"
volumes:
- ./backend/services/accounting:/app
- ./backend/shared-lib:/shared-lib
depends_on:
postgres:
condition: service_healthy
core-service:
condition: service_started
command: >
sh -c "python scripts/ensure_db.py &&
alembic upgrade head &&
uvicorn app.main:app --host 0.0.0.0 --port 8002 --reload"
networks:
- superapp_net
crm-service:
build:
context: .
dockerfile: backend/services/crm/Dockerfile.dev
container_name: superapp_crm_service
restart: unless-stopped
env_file:
- .env
environment:
CRM_DATABASE_URL: ${CRM_DATABASE_URL}
CRM_DATABASE_URL_SYNC: ${CRM_DATABASE_URL_SYNC}
CORE_SERVICE_URL: ${CORE_SERVICE_URL:-http://core-service:8000}
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000}
AUTH_REQUIRED: ${AUTH_REQUIRED:-true}
KEYCLOAK_SERVER_URL: ${KEYCLOAK_SERVER_URL:-http://keycloak:8080}
KEYCLOAK_PUBLIC_URL: ${KEYCLOAK_PUBLIC_URL:-http://localhost:8080}
KEYCLOAK_REALM: ${KEYCLOAK_REALM:-superapp}
JWT_VERIFY_SIGNATURE: ${JWT_VERIFY_SIGNATURE:-true}
ports:
- "8003:8003"
volumes:
- ./backend/services/crm:/app
- ./backend/shared-lib:/shared-lib
depends_on:
postgres:
condition: service_healthy
core-service:
condition: service_started
command: >
sh -c "python scripts/ensure_db.py &&
alembic upgrade head &&
uvicorn app.main:app --host 0.0.0.0 --port 8003 --reload"
networks:
- superapp_net
loyalty-service:
build:
context: .
dockerfile: backend/services/loyalty/Dockerfile.dev
container_name: superapp_loyalty_service
restart: unless-stopped
env_file:
- .env
environment:
LOYALTY_DATABASE_URL: ${LOYALTY_DATABASE_URL}
LOYALTY_DATABASE_URL_SYNC: ${LOYALTY_DATABASE_URL_SYNC}
CORE_SERVICE_URL: ${CORE_SERVICE_URL:-http://core-service:8000}
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000}
AUTH_REQUIRED: ${AUTH_REQUIRED:-true}
KEYCLOAK_SERVER_URL: ${KEYCLOAK_SERVER_URL:-http://keycloak:8080}
KEYCLOAK_PUBLIC_URL: ${KEYCLOAK_PUBLIC_URL:-http://localhost:8080}
KEYCLOAK_REALM: ${KEYCLOAK_REALM:-superapp}
JWT_VERIFY_SIGNATURE: ${JWT_VERIFY_SIGNATURE:-true}
ports:
- "8004:8004"
volumes:
- ./backend/services/loyalty:/app
- ./backend/shared-lib:/shared-lib
depends_on:
postgres:
condition: service_healthy
core-service:
condition: service_started
command: >
sh -c "python scripts/ensure_db.py &&
alembic upgrade head &&
uvicorn app.main:app --host 0.0.0.0 --port 8004 --reload"
networks:
- superapp_net
communication-service:
build:
context: .
dockerfile: backend/services/communication/Dockerfile.dev
container_name: superapp_communication_service
restart: unless-stopped
env_file:
- .env
environment:
COMMUNICATION_DATABASE_URL: ${COMMUNICATION_DATABASE_URL}
COMMUNICATION_DATABASE_URL_SYNC: ${COMMUNICATION_DATABASE_URL_SYNC}
CORE_SERVICE_URL: ${CORE_SERVICE_URL:-http://core-service:8000}
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000}
AUTH_REQUIRED: ${AUTH_REQUIRED:-true}
KEYCLOAK_SERVER_URL: ${KEYCLOAK_SERVER_URL:-http://keycloak:8080}
KEYCLOAK_PUBLIC_URL: ${KEYCLOAK_PUBLIC_URL:-http://localhost:8080}
KEYCLOAK_REALM: ${KEYCLOAK_REALM:-superapp}
JWT_VERIFY_SIGNATURE: ${JWT_VERIFY_SIGNATURE:-true}
ports:
- "8005:8005"
volumes:
- ./backend/services/communication:/app
- ./backend/shared-lib:/shared-lib
depends_on:
postgres:
condition: service_healthy
core-service:
condition: service_started
command: >
sh -c "python scripts/ensure_db.py &&
alembic upgrade head &&
uvicorn app.main:app --host 0.0.0.0 --port 8005 --reload"
networks:
- superapp_net
sports-center-service:
build:
context: .
dockerfile: backend/services/sports_center/Dockerfile.dev
container_name: superapp_sports_center_service
restart: unless-stopped
env_file:
- .env
environment:
SPORTS_CENTER_DATABASE_URL: ${SPORTS_CENTER_DATABASE_URL}
SPORTS_CENTER_DATABASE_URL_SYNC: ${SPORTS_CENTER_DATABASE_URL_SYNC}
CORE_SERVICE_URL: ${CORE_SERVICE_URL:-http://core-service:8000}
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000}
AUTH_REQUIRED: ${AUTH_REQUIRED:-true}
KEYCLOAK_SERVER_URL: ${KEYCLOAK_SERVER_URL:-http://keycloak:8080}
KEYCLOAK_PUBLIC_URL: ${KEYCLOAK_PUBLIC_URL:-http://localhost:8080}
KEYCLOAK_REALM: ${KEYCLOAK_REALM:-superapp}
JWT_VERIFY_SIGNATURE: ${JWT_VERIFY_SIGNATURE:-true}
ports:
- "8006:8006"
volumes:
- ./backend/services/sports_center:/app
- ./backend/shared-lib:/shared-lib
depends_on:
postgres:
condition: service_healthy
core-service:
condition: service_started
command: >
sh -c "python scripts/ensure_db.py &&
alembic upgrade head &&
uvicorn app.main:app --host 0.0.0.0 --port 8006 --reload"
networks:
- superapp_net
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
container_name: superapp_frontend
restart: unless-stopped
ports:
- "${FRONTEND_PORT:-3000}:3000"
environment:
NEXT_PUBLIC_BACKEND_URL: ${NEXT_PUBLIC_BACKEND_URL:-http://localhost:8000}
NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL:-http://localhost:8000}
NEXT_PUBLIC_IDENTITY_API_URL: ${NEXT_PUBLIC_IDENTITY_API_URL:-http://localhost:8001}
NEXT_PUBLIC_KEYCLOAK_URL: ${NEXT_PUBLIC_KEYCLOAK_URL:-http://localhost:8080}
NEXT_PUBLIC_KEYCLOAK_REALM: ${NEXT_PUBLIC_KEYCLOAK_REALM:-superapp}
NEXT_PUBLIC_KEYCLOAK_CLIENT_ID: ${NEXT_PUBLIC_KEYCLOAK_CLIENT_ID:-superapp-frontend}
NEXT_PUBLIC_PLATFORM_BASE_DOMAIN: ${NEXT_PUBLIC_PLATFORM_BASE_DOMAIN:-torbatyar.ir}
NEXT_PUBLIC_ACCOUNTING_API_URL: ${NEXT_PUBLIC_ACCOUNTING_API_URL:-http://localhost:8002}
ACCOUNTING_SERVICE_URL: ${ACCOUNTING_SERVICE_URL:-http://accounting-service:8002}
# polling برای hot-reload پایدار روی volume mount ویندوز
WATCHPACK_POLLING: "true"
CHOKIDAR_USEPOLLING: "true"
volumes:
- ./frontend:/app
- frontend_node_modules:/app/node_modules
depends_on:
core-service:
condition: service_started
identity-access-service:
condition: service_started
networks:
- superapp_net
celery-worker:
build:
context: .
dockerfile: backend/core-service/Dockerfile.dev
container_name: superapp_celery_worker
restart: unless-stopped
env_file:
- .env
volumes:
- ./backend/core-service:/app
- ./backend/shared-lib:/shared-lib
depends_on:
redis:
condition: service_healthy
postgres:
condition: service_healthy
command: celery -A app.workers.celery_app.celery_app worker --loglevel=INFO -Q default,core_events,notifications,webhooks
networks:
- superapp_net
celery-beat:
build:
context: .
dockerfile: backend/core-service/Dockerfile.dev
container_name: superapp_celery_beat
restart: unless-stopped
env_file:
- .env
volumes:
- ./backend/core-service:/app
- ./backend/shared-lib:/shared-lib
depends_on:
redis:
condition: service_healthy
command: celery -A app.workers.celery_app.celery_app beat --loglevel=INFO
networks:
- superapp_net
volumes:
postgres_data:
redis_data:
frontend_node_modules:
networks:
superapp_net:
driver: bridge