version: '3.2'

networks:
  mongo:
    driver: bridge
  redis:
    driver: bridge
  rabbitmq:
    driver: bridge
  ory:
    driver: bridge
  apps:
    driver: bridge

volumes:
  mongo_volume:
  redis_volume:
  rabbitmq_volume:
  kratos_postgres_volume:
  hydra_postgres_volume:
  keto_postgres_volume:

services:
  # region Storage
  mongo-primary:
    image: mongo:7
    container_name: ticketing-mongo-primary
    hostname: ticketing-mongo-primary
    volumes:
      - mongo_volume:/data/db
    networks:
      - mongo
    ports:
      - '${MONGO_PORT:-27017}:27017'
    command: mongod --replSet rs0
    healthcheck:
      test: |
        mongosh --eval "try { rs.status().ok } catch (e) { rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: 'localhost:27017' }] }).ok }"
      start_period: 0s
      interval: 500ms
      timeout: 5s
      retries: 5
    profiles:
      - 'deps-only'
      - 'dev'

  redis:
    image: redis:alpine
    container_name: ticketing-redis
    hostname: ticketing-redis
    volumes:
      - redis_volume:/data
    networks:
      - redis
    ports:
      - '${REDIS_PORT:-6379}:6379'
    mem_limit: 256m
    memswap_limit: 512m
    restart: always
    profiles:
      - 'deps-only'
      - 'dev'

  # endregion

  # region RabbitMQ
  rabbitmq:
    image: rabbitmq:3.12-management-alpine
    container_name: 'ticketing-rabbitmq'
    hostname: ticketing-rabbitmq
    healthcheck:
      test: ['CMD', 'rabbitmq-diagnostics', 'status']
      interval: '10s'
      timeout: '15s'
      start_period: '30s'
      retries: 3
    volumes:
      - ./infra/rabbitmq/etc/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
      # - ./infra/rabbitmq/etc/definitions.json:/etc/rabbitmq/definitions.json
      - ./infra/rabbitmq/etc/enabled_plugins:/etc/rabbitmq/enabled_plugins
      - rabbitmq_volume:/var/lib/rabbitmq/mnesia/rabbit@ticketing-rabbitmq
    ports:
      - ${RABBITMQ_PORT:-5672}:5672
      - ${RABBITMQ_MGT_PORT:-15672}:15672
      - ${RABBITMQ_MQTT_PORT:-1883}:1883
      - ${RABBITMQ_WS_PORT:-15675}:15675
    networks:
      - rabbitmq
    restart: always
    profiles:
      - 'deps-only'
      - 'dev'
    # for docker on linux
    # extra_hosts:
    #   - "host.docker.internal:host-gateway"

  # endregion

  # region micro services
  auth-service:
    image: 'ghcr.io/getlarge/ticketing-auth:${AUTH_IMAGE_VERSION:-latest}'
    container_name: auth-service
    hostname: auth-service
    environment:
      NODE_ENV: ${NODE_ENV:-development}
      LOG_LEVEL: ${LOG_LEVEL:-info}
      PORT: ${AUTH_HTTP_PORT:-3000}
      SERVER_URL: http://localhost:${AUTH_HTTP_PORT:-3000}
      PROXY_SERVER_URLS: ${PROXY_SERVER_URLS:-http://ticketing.dev}
      FRONTEND_URL: ${FRONTEND_URL:-http://ticketing.dev}
      JWT_ALGORITHM: ${JWT_ALGORITHM:-ES256}
      JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-60m}
      JWT_ISSUER: ${JWT_ISSUER:-ticketing.dev}
      JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
      JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY}
      SESSION_KEY: ${SESSION_KEY}
      RMQ_URL: http://ticketing-rabbitmq:5672
      MONGODB_URI: mongodb://ticketing-mongo-primary:27017/auth
      ORY_ACTION_API_KEY: ${ORY_ACTION_API_KEY}
      ORY_API_KEY: ${ORY_API_KEY}
      ORY_BASE_PATH: ${ORY_BASE_PATH}
    healthcheck:
      test: node ./healthcheck.js http://0.0.0.0:${AUTH_HTTP_PORT:-3000}/$GLOBAL_API_PREFIX/health
      interval: 60s
      timeout: 3s
      start_period: 10s
      retries: 2
    depends_on:
      - mongo-primary
      - rabbitmq
    ports:
      - '${AUTH_HTTP_PORT:-3000}:${AUTH_HTTP_PORT:-3000}'
    networks:
      - mongo
      - rabbitmq
      - apps
    mem_limit: 256m
    memswap_limit: 512m
    restart: always
    profiles:
      - 'services-only'
      - 'dev'

  expiration-service:
    image: 'ghcr.io/getlarge/ticketing-expiration:${EXPIRATION_IMAGE_VERSION:-latest}'
    container_name: expiration-service
    hostname: expiration-service
    environment:
      NODE_ENV: ${NODE_ENV:-development}
      LOG_LEVEL: ${LOG_LEVEL:-info}
      PORT: ${EXPIRATION_HTTP_PORT:-3030}
      SERVER_URL: http://localhost:${EXPIRATION_HTTP_PORT:-3030}
      PROXY_SERVER_URLS: ${PROXY_SERVER_URLS:-http://ticketing.dev}
      RMQ_URL: http://ticketing-rabbitmq:5672
      REDIS_URL: redis://ticketing-redis:6379
      ORY_API_KEY: ${ORY_API_KEY}
      ORY_BASE_PATH: ${ORY_BASE_PATH}
    healthcheck:
      test: node ./healthcheck.js http://0.0.0.0:${EXPIRATION_HTTP_PORT:-3000}/${GLOBAL_API_PREFIX:-api}/health
      interval: 60s
      timeout: 3s
      start_period: 10s
      retries: 2
    depends_on:
      - redis
      - rabbitmq
    ports:
      - '${EXPIRATION_HTTP_PORT:-3030}:${EXPIRATION_HTTP_PORT:-3030}'
    networks:
      - redis
      - rabbitmq
      - apps
    mem_limit: 256m
    memswap_limit: 512m
    restart: always
    profiles:
      - 'services-only'
      - 'dev'

  orders-service:
    image: 'ghcr.io/getlarge/ticketing-orders:${ORDERS_IMAGE_VERSION:-latest}'
    container_name: orders-service
    hostname: orders-service
    environment:
      NODE_ENV: ${NODE_ENV:-development}
      LOG_LEVEL: ${LOG_LEVEL:-info}
      PORT: ${ORDERS_HTTP_PORT:-3020}
      SERVER_URL: http://localhost:${ORDERS_HTTP_PORT:-3020}
      PROXY_SERVER_URLS: ${PROXY_SERVER_URLS:-http://ticketing.dev}
      FRONTEND_URL: ${FRONTEND_URL:-http://ticketing.dev}
      JWT_ALGORITHM: ${JWT_ALGORITHM:-ES256}
      JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-60m}
      JWT_ISSUER: ${JWT_ISSUER:-ticketing.dev}
      JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
      JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY}
      SESSION_KEY: ${SESSION_KEY}
      RMQ_URL: http://ticketing-rabbitmq:5672
      MONGODB_URI: mongodb://ticketing-mongo-primary:27017/orders
      ORY_API_KEY: ${ORY_API_KEY}
      ORY_BASE_PATH: ${ORY_BASE_PATH}
    healthcheck:
      test: node ./healthcheck.js http://0.0.0.0:${ORDERS_HTTP_PORT:-3020}/${GLOBAL_API_PREFIX:-api}/health
      interval: 60s
      timeout: 3s
      start_period: 10s
      retries: 2
    depends_on:
      - mongo-primary
      - rabbitmq
    ports:
      - '${ORDERS_HTTP_PORT:-3020}:${ORDERS_HTTP_PORT:-3020}'
    networks:
      - mongo
      - rabbitmq
      - apps
    mem_limit: 256m
    memswap_limit: 512m
    restart: always
    profiles:
      - 'services-only'
      - 'dev'

  payments-service:
    image: 'ghcr.io/getlarge/ticketing-payments:${PAYMENTS_IMAGE_VERSION:-latest}'
    container_name: payments-service
    hostname: payments-service
    environment:
      NODE_ENV: ${NODE_ENV:-development}
      LOG_LEVEL: ${LOG_LEVEL:-info}
      PORT: ${PAYMENTS_HTTP_PORT:-3040}
      SERVER_URL: http://localhost:${PAYMENTS_HTTP_PORT:-3040}
      PROXY_SERVER_URLS: ${PROXY_SERVER_URLS:-http://ticketing.dev}
      FRONTEND_URL: ${FRONTEND_URL:-http://ticketing.dev}
      JWT_ALGORITHM: ${JWT_ALGORITHM:-ES256}
      JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-60m}
      JWT_ISSUER: ${JWT_ISSUER:-ticketing.dev}
      JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
      JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY}
      SESSION_KEY: ${SESSION_KEY}
      RMQ_URL: http://ticketing-rabbitmq:5672
      MONGODB_URI: mongodb://ticketing-mongo-primary:27017/payments
      STRIPE_PUBLISHABLE_KEY: ${STRIPE_PUBLISHABLE_KEY}
      STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
      STRIPE_ENDPOINT_SECRET: ${STRIPE_ENDPOINT_SECRET}
      ORY_API_KEY: ${ORY_API_KEY}
      ORY_BASE_PATH: ${ORY_BASE_PATH}
    healthcheck:
      test: node ./healthcheck.js http://0.0.0.0:${PAYMENTS_HTTP_PORT:-3040}/${GLOBAL_API_PREFIX:-api}/health
      interval: 60s
      timeout: 3s
      start_period: 10s
      retries: 2
    depends_on:
      - mongo-primary
      - rabbitmq
    ports:
      - '${PAYMENTS_HTTP_PORT:-3040}:${PAYMENTS_HTTP_PORT:-3040}'
    networks:
      - mongo
      - rabbitmq
      - apps
    mem_limit: 256m
    memswap_limit: 512m
    restart: always
    profiles:
      - 'services-only'
      - 'dev'

  tickets-service:
    image: 'ghcr.io/getlarge/ticketing-tickets:${TICKETS_IMAGE_VERSION:-latest}'
    container_name: tickets-service
    hostname: tickets-service
    environment:
      NODE_ENV: ${NODE_ENV:-development}
      LOG_LEVEL: ${LOG_LEVEL:-info}
      PORT: ${TICKETS_HTTP_PORT:-3010}
      SERVER_URL: http://localhost:${TICKETS_HTTP_PORT:-3010}
      PROXY_SERVER_URLS: ${PROXY_SERVER_URLS:-http://ticketing.dev}
      FRONTEND_URL: ${FRONTEND_URL:-http://ticketing.dev}
      JWT_ALGORITHM: ${JWT_ALGORITHM:-ES256}
      JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-60m}
      JWT_ISSUER: ${JWT_ISSUER:-ticketing.dev}
      JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
      JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY}
      SESSION_KEY: ${SESSION_KEY}
      RMQ_URL: http://ticketing-rabbitmq:5672
      MONGODB_URI: mongodb://ticketing-mongo-primary:27017/tickets
      ORY_API_KEY: ${ORY_API_KEY}
      ORY_BASE_PATH: ${ORY_BASE_PATH}
    healthcheck:
      test: node ./healthcheck.js http://0.0.0.0:${TICKETS_HTTP_PORT:-3010}/${GLOBAL_API_PREFIX:-api}/health
      interval: 60s
      timeout: 3s
      start_period: 10s
      retries: 2
    depends_on:
      - mongo-primary
      - rabbitmq
    ports:
      - '${TICKETS_HTTP_PORT:-3010}:${TICKETS_HTTP_PORT:-3010}'
    networks:
      - mongo
      - rabbitmq
      - apps
    mem_limit: 256m
    memswap_limit: 512m
    restart: always
    profiles:
      - 'services-only'
      - 'dev'

  # endregion

  # region Frontend
  ng-client:
    image: 'ghcr.io/getlarge/ticketing-ng-client:${CLIENT_IMAGE_VERSION:-latest}'
    container_name: ng-client
    hostname: ng-client
    healthcheck:
      test: curl -f http://localhost:4200
    ports:
      - '4200:4200'
    networks:
      - apps
    mem_limit: 256m
    memswap_limit: 512m
    restart: always
    profiles:
      - 'services-only'
      - 'dev'

  nginx:
    container_name: ticketing-nginx
    build:
      context: infra/nginx
      dockerfile: Dockerfile
      args:
        - TEMPLATE=nginx.template
    environment:
      - DOMAIN=${DOMAIN:-localhost}
      - FRONTEND_PORT=3000
      - FRONTEND=ng-client
      - AUTH_SERVICE=auth-service
      - ORDERS_SERVICE=orders-service
      - PAYMENTS_SERVICE=payments-service
      - TICKETS_SERVICE=tickets-service
      - AUTH_SERVICE_PORT=${AUTH_SERVICE_PORT:-3000}
      - ORDERS_SERVICE_PORT=${ORDERS_SERVICE_PORT:-3020}
      - PAYMENTS_SERVICE_PORT=${PAYMENTS_SERVICE_PORT:-3040}
      - TICKETS_SERVICE_PORT=${TICKETS_SERVICE_PORT:-3010}
    depends_on:
      ng-client:
        condition: service_started
      auth-service:
        condition: service_started
      orders-service:
        condition: service_started
      payments-service:
        condition: service_started
      tickets-service:
        condition: service_started
        # condition: service_healthy
    networks:
      - apps
    ports:
      - '127.0.0.1:${NGINX_HTTP_PORT:-8800}:8080'
    restart: always
    profiles:
      - 'services-only'
      - 'dev'
    # for docker on linux
    # extra_hosts:
    #   - "host.docker.internal:host-gateway"

  # endregion

  # region Ory Kratos
  kratos-migrate:
    image: oryd/kratos:v1.1.0
    volumes:
      - ./infra/ory/kratos:/etc/config/kratos:ro
    command: -c /etc/config/kratos/kratos.yaml migrate sql -e --yes
    restart: on-failure
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'

  kratos:
    depends_on:
      - kratos-migrate
    image: oryd/kratos:v1.1.0
    ports:
      - '4433:4433' # public
      - '4434:4434' # admin
    restart: unless-stopped
    command: serve -c /etc/config/kratos/kratos.yaml --dev --watch-courier
    volumes:
      - ./infra/ory/kratos:/etc/config/kratos:ro
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'
    # for docker on linux
    # extra_hosts:
    #   - "host.docker.internal:host-gateway"

  kratos-postgres:
    image: postgres:16
    environment:
      - POSTGRES_USER=dbuser
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=kratosdb
    volumes:
      - kratos_postgres_volume:/var/lib/postgresql/data
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'

  kratos-selfservice-ui-node:
    image: oryd/kratos-selfservice-ui-node:v1.1.0
    environment:
      - KRATOS_PUBLIC_URL=http://kratos:4433
      - KRATOS_BROWSER_URL=http://127.0.0.1:4433
      - HYDRA_ADMIN_URL=http://hydra:4445
      - KRATOS_ADMIN_URL=http://kratos:4434
      - PORT=4455
      - COOKIE_SECRET=changeme
      - CSRF_COOKIE_NAME=cookie_name
      - CSRF_COOKIE_SECRET=changeme
      - DANGEROUSLY_DISABLE_SECURE_CSRF_COOKIES=true
    ports:
      - '4455:4455'
    networks:
      - ory
    restart: on-failure
    profiles:
      - 'ory-only'
      - 'dev'

  mailslurper:
    image: oryd/mailslurper:latest-smtps
    ports:
      - '4436:4436'
      - '4437:4437'
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'
  # endregion

  #region Hydra

  hydra-migrate:
    image: oryd/hydra:v2.2.0
    command: migrate -c /etc/config/hydra/hydra.yaml sql -e --yes
    volumes:
      - ./infra/ory/hydra:/etc/config/hydra:ro
    restart: on-failure
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'

  hydra:
    image: oryd/hydra:v2.2.0
    ports:
      - '4444:4444' # public
      - '4445:4445' # admin
      - '5555:5555' # port to use for OAuth2 redirect URIs
    command: serve -c /etc/config/hydra/hydra.yaml all --dev
    volumes:
      - ./infra/ory/hydra:/etc/config/hydra:ro
    restart: unless-stopped
    depends_on:
      - hydra-migrate
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'

  hydra-postgres:
    image: postgres:16
    environment:
      - POSTGRES_USER=dbuser
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=hydradb
    volumes:
      - hydra_postgres_volume:/var/lib/postgresql/data
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'

  # endregion

  # region Ory Keto
  keto-migrate:
    image: oryd/keto:v0.12.0
    volumes:
      - ./infra/ory/keto:/etc/config/keto:ro
      - ./tools/ory/namespaces.ts:/home/ory/namespaces.ts
    command: ['migrate', 'up', '-y', '-c', '/etc/config/keto/keto.yaml']
    restart: on-failure
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'

  keto:
    depends_on:
      - keto-migrate
    image: oryd/keto:v0.12.0
    ports:
      - '4466:4466' # public
      - '4467:4467' # admin
    command: serve -c /etc/config/keto/keto.yaml
    restart: unless-stopped
    volumes:
      - ./infra/ory/keto:/etc/config/keto:ro
      - ./tools/ory/namespaces.ts:/home/ory/namespaces.ts
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'

  keto-postgres:
    image: postgres:16
    environment:
      - POSTGRES_USER=dbuser
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=accesscontroldb
    volumes:
      - keto_postgres_volume:/var/lib/postgresql/data
    networks:
      - ory
    profiles:
      - 'ory-only'
      - 'dev'

  # endregion