| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| name: fineract-business-intelligence |
| |
| services: |
| fineract-db: |
| image: postgres:18.3 |
| container_name: fineract-bi-fineract-db |
| environment: |
| POSTGRES_DB: postgres |
| POSTGRES_USER: ${SOURCE_BOOTSTRAP_USER:?SOURCE_BOOTSTRAP_USER must be set} |
| POSTGRES_PASSWORD: ${SOURCE_BOOTSTRAP_PASSWORD:?SOURCE_BOOTSTRAP_PASSWORD must be set} |
| FINERACT_APP_USER: ${SOURCE_APP_USER:?SOURCE_APP_USER must be set} |
| FINERACT_APP_PASSWORD: ${SOURCE_APP_PASSWORD:?SOURCE_APP_PASSWORD must be set} |
| FINERACT_TENANTS_DB_NAME: ${SOURCE_TENANTS_DB_NAME:?SOURCE_TENANTS_DB_NAME must be set} |
| FINERACT_DEFAULT_DB_NAME: ${SOURCE_DB_NAME:?SOURCE_DB_NAME must be set} |
| SOURCE_REPLICA_USER: ${SOURCE_REPLICA_USER:?SOURCE_REPLICA_USER must be set} |
| SOURCE_REPLICA_PASSWORD: ${SOURCE_REPLICA_PASSWORD:?SOURCE_REPLICA_PASSWORD must be set} |
| ports: |
| - "5433:5432" |
| volumes: |
| - fineract_db_data:/var/lib/postgresql |
| - ./docker/fineract-postgresql/initdb:/docker-entrypoint-initdb.d:ro |
| healthcheck: |
| test: ["CMD-SHELL", "pg_isready -U ${SOURCE_BOOTSTRAP_USER:?SOURCE_BOOTSTRAP_USER must be set} -d postgres"] |
| interval: 10s |
| timeout: 5s |
| retries: 10 |
| |
| warehouse: |
| image: postgres:16-alpine |
| container_name: fineract-bi-warehouse |
| environment: |
| POSTGRES_DB: ${WAREHOUSE_DB_NAME:?WAREHOUSE_DB_NAME must be set} |
| POSTGRES_USER: ${WAREHOUSE_ADMIN_USER:?WAREHOUSE_ADMIN_USER must be set} |
| POSTGRES_PASSWORD: ${WAREHOUSE_ADMIN_PASSWORD:?WAREHOUSE_ADMIN_PASSWORD must be set} |
| WAREHOUSE_LOADER_USER: ${WAREHOUSE_LOADER_USER:?WAREHOUSE_LOADER_USER must be set} |
| WAREHOUSE_LOADER_PASSWORD: ${WAREHOUSE_LOADER_PASSWORD:?WAREHOUSE_LOADER_PASSWORD must be set} |
| WAREHOUSE_READER_USER: ${WAREHOUSE_READER_USER:?WAREHOUSE_READER_USER must be set} |
| WAREHOUSE_READER_PASSWORD: ${WAREHOUSE_READER_PASSWORD:?WAREHOUSE_READER_PASSWORD must be set} |
| ports: |
| - "5434:5432" |
| volumes: |
| - warehouse_data:/var/lib/postgresql/data |
| - ./docker/postgres-warehouse/initdb:/docker-entrypoint-initdb.d:ro |
| - ./warehouse/schema:/warehouse-schema:ro |
| healthcheck: |
| test: ["CMD-SHELL", "pg_isready -U ${WAREHOUSE_ADMIN_USER:?WAREHOUSE_ADMIN_USER must be set} -d ${WAREHOUSE_DB_NAME:?WAREHOUSE_DB_NAME must be set}"] |
| interval: 10s |
| timeout: 5s |
| retries: 10 |
| |
| extractor: |
| build: |
| context: . |
| dockerfile: docker/extractor/Dockerfile |
| container_name: fineract-bi-extractor |
| depends_on: |
| warehouse: |
| condition: service_healthy |
| environment: |
| SOURCE_DB_HOST: ${SOURCE_DB_HOST:-host.docker.internal} |
| SOURCE_DB_PORT: ${SOURCE_DB_HOST_PORT:-5432} |
| SOURCE_DB_NAME: ${SOURCE_DB_NAME:?SOURCE_DB_NAME must be set} |
| SOURCE_DB_USER: ${SOURCE_REPLICA_USER:?SOURCE_REPLICA_USER must be set} |
| SOURCE_DB_PASSWORD: ${SOURCE_REPLICA_PASSWORD:?SOURCE_REPLICA_PASSWORD must be set} |
| SOURCE_DB_SCHEMA: ${SOURCE_DB_SCHEMA:-public} |
| WAREHOUSE_DB_HOST: warehouse |
| WAREHOUSE_DB_PORT: "5432" |
| WAREHOUSE_DB_NAME: ${WAREHOUSE_DB_NAME:?WAREHOUSE_DB_NAME must be set} |
| WAREHOUSE_DB_USER: ${WAREHOUSE_LOADER_USER:?WAREHOUSE_LOADER_USER must be set} |
| WAREHOUSE_DB_PASSWORD: ${WAREHOUSE_LOADER_PASSWORD:?WAREHOUSE_LOADER_PASSWORD must be set} |
| WAREHOUSE_DB_SCHEMA: ${WAREHOUSE_DB_SCHEMA:-raw} |
| TENANT_ID: ${TENANT_ID:-default} |
| REPLICA_LAG_THRESHOLD_SECONDS: "300" |
| COB_LOOKBACK_HOURS: "9999" |
| EXTRACT_LOOKBACK_SECONDS: "600" |
| PIPELINE_MODE: ${PIPELINE_MODE:-incremental} |
| PIPELINE_INTERVAL_SECONDS: ${PIPELINE_INTERVAL_SECONDS:-3600} |
| PYTHONPATH: /app |
| PYTHONUNBUFFERED: "1" |
| networks: |
| - default |
| - fineract_network |
| volumes: |
| - .:/app |
| - /var/run/docker.sock:/var/run/docker.sock |
| working_dir: /app |
| command: > |
| bash -c " |
| echo '[pipeline] Waiting 30s for Superset to finish initialising...'; |
| sleep 30; |
| bash /app/scripts/run_pipeline.sh backfill; |
| while true; do |
| bash /app/scripts/run_pipeline.sh incremental || true; |
| echo \"[pipeline] Sleeping \$${PIPELINE_INTERVAL_SECONDS}s\"; |
| sleep \$${PIPELINE_INTERVAL_SECONDS}; |
| done |
| " |
| |
| dbt: |
| build: |
| context: . |
| dockerfile: docker/dbt/Dockerfile |
| container_name: fineract-bi-dbt |
| depends_on: |
| warehouse: |
| condition: service_healthy |
| environment: |
| PGHOST: warehouse |
| PGPORT: "5432" |
| PGDATABASE: ${WAREHOUSE_DB_NAME:?WAREHOUSE_DB_NAME must be set} |
| PGUSER: ${WAREHOUSE_LOADER_USER:?WAREHOUSE_LOADER_USER must be set} |
| PGPASSWORD: ${WAREHOUSE_LOADER_PASSWORD:?WAREHOUSE_LOADER_PASSWORD must be set} |
| TENANT_ID: ${TENANT_ID:-default} |
| DBT_PROFILES_DIR: /app/dbt |
| volumes: |
| - .:/app |
| working_dir: /app/dbt |
| command: ["tail", "-f", "/dev/null"] |
| |
| superset: |
| build: |
| context: . |
| dockerfile: docker/superset/Dockerfile |
| container_name: fineract-bi-superset |
| depends_on: |
| warehouse: |
| condition: service_healthy |
| ports: |
| - "8088:8088" |
| environment: |
| SUPERSET_CONFIG_PATH: /workspace/docker/superset/superset_config.py |
| SUPERSET_SECRET_KEY: ${SUPERSET_SECRET_KEY:?SUPERSET_SECRET_KEY must be set} |
| SUPERSET_ADMIN_USERNAME: ${SUPERSET_ADMIN_USERNAME:-admin} |
| SUPERSET_ADMIN_FIRSTNAME: ${SUPERSET_ADMIN_FIRSTNAME:-Admin} |
| SUPERSET_ADMIN_LASTNAME: ${SUPERSET_ADMIN_LASTNAME:-User} |
| SUPERSET_ADMIN_EMAIL: ${SUPERSET_ADMIN_EMAIL:-admin@example.com} |
| SUPERSET_ADMIN_PASSWORD: ${SUPERSET_ADMIN_PASSWORD:?SUPERSET_ADMIN_PASSWORD must be set} |
| SUPERSET_NORTH_MANAGER_PASSWORD: ${SUPERSET_NORTH_MANAGER_PASSWORD:?SUPERSET_NORTH_MANAGER_PASSWORD must be set} |
| SUPERSET_SOUTH_MANAGER_PASSWORD: ${SUPERSET_SOUTH_MANAGER_PASSWORD:?SUPERSET_SOUTH_MANAGER_PASSWORD must be set} |
| SUPERSET_METADATA_URI: postgresql+psycopg2://${WAREHOUSE_ADMIN_USER:?WAREHOUSE_ADMIN_USER must be set}:${WAREHOUSE_ADMIN_PASSWORD:?WAREHOUSE_ADMIN_PASSWORD must be set}@warehouse:5432/superset_metadata |
| SUPERSET_WAREHOUSE_URI: postgresql+psycopg2://${WAREHOUSE_READER_USER:?WAREHOUSE_READER_USER must be set}:${WAREHOUSE_READER_PASSWORD:?WAREHOUSE_READER_PASSWORD must be set}@warehouse:5432/${WAREHOUSE_DB_NAME:?WAREHOUSE_DB_NAME must be set} |
| volumes: |
| - .:/workspace |
| - superset_home:/app/superset_home |
| command: ["bash", "/workspace/docker/superset/init_superset.sh"] |
| healthcheck: |
| test: ["CMD-SHELL", "curl -sf http://localhost:8088/health | grep -q 'OK'"] |
| interval: 15s |
| timeout: 10s |
| retries: 10 |
| start_period: 60s |
| |
| volumes: |
| fineract_db_data: |
| warehouse_data: |
| superset_home: |
| |
| networks: |
| default: |
| name: fineract-business-intelligence_default |
| fineract_network: |
| external: true |
| name: fineract_default |