x-custom-image: &custom_image
  image: ${IMAGE_NAME:-ghcr.io/frappe/hrms}:${VERSION:-version-15}
  pull_policy: ${PULL_POLICY:-always}
  deploy:
    restart_policy:
      condition: always

services:
  backend:
    <<: *custom_image
    volumes:
      - sites:/home/frappe/frappe-bench/sites
    networks:
      - bench-network
    healthcheck:
      test:
        - CMD
        - wait-for-it
        - '0.0.0.0:8000'
      interval: 2s
      timeout: 10s
      retries: 30

  frontend:
    <<: *custom_image
    command:
      - nginx-entrypoint.sh
    depends_on:
      backend:
        condition: service_started
        required: true
      websocket:
        condition: service_started
        required: true
    environment:
      BACKEND: backend:8000
      FRAPPE_SITE_NAME_HEADER: ${FRAPPE_SITE_NAME_HEADER:-$$host}
      SOCKETIO: websocket:9000
      UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
      UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
      UPSTREAM_REAL_IP_RECURSIVE: "off"
    volumes:
      - sites:/home/frappe/frappe-bench/sites

    networks:
      - bench-network
    
    healthcheck:
      test:
        - CMD
        - wait-for-it
        - '0.0.0.0:8080'
      interval: 2s
      timeout: 30s
      retries: 30

  queue-default:
    <<: *custom_image
    command:
      - bench
      - worker
      - --queue
      - default
    volumes:
      - sites:/home/frappe/frappe-bench/sites
    networks:
      - bench-network
    healthcheck:
      test:
        - CMD
        - wait-for-it
        - 'redis-queue:6379'
      interval: 2s
      timeout: 10s
      retries: 30
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true

  queue-long:
    <<: *custom_image
    command:
      - bench
      - worker
      - --queue
      - long
    volumes:
      - sites:/home/frappe/frappe-bench/sites
    networks:
      - bench-network
    healthcheck:
      test:
        - CMD
        - wait-for-it
        - 'redis-queue:6379'
      interval: 2s
      timeout: 10s
      retries: 30
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true

  queue-short:
    <<: *custom_image
    command:
      - bench
      - worker
      - --queue
      - short
    volumes:
      - sites:/home/frappe/frappe-bench/sites
    networks:
      - bench-network
    healthcheck:
      test:
        - CMD
        - wait-for-it
        - 'redis-queue:6379'
      interval: 2s
      timeout: 10s
      retries: 30
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true

  scheduler:
    <<: *custom_image
    healthcheck:
      test:
        - CMD
        - wait-for-it
        - 'redis-queue:6379'
      interval: 2s
      timeout: 10s
      retries: 30
    command:
      - bench
      - schedule
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true
    volumes:
      - sites:/home/frappe/frappe-bench/sites
    networks:
      - bench-network

  websocket:
    <<: *custom_image
    healthcheck:
      test:
        - CMD
        - wait-for-it
        - '0.0.0.0:9000'
      interval: 2s
      timeout: 10s
      retries: 30
    command:
      - node
      - /home/frappe/frappe-bench/apps/frappe/socketio.js
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true
    volumes:
      - sites:/home/frappe/frappe-bench/sites
    networks:
      - bench-network

  configurator:
    <<: *custom_image
    deploy:
      mode: replicated
      replicas: ${CONFIGURE:-0}
      restart_policy:
        condition: none
    entrypoint: ["bash", "-c"]
    command:
      - >
        [[ $${REGENERATE_APPS_TXT} == "1" ]] && ls -1 apps > sites/apps.txt;
        [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && exit 0;
        bench set-config -g db_host $$DB_HOST;
        bench set-config -gp db_port $$DB_PORT;
        bench set-config -g redis_cache "redis://$$REDIS_CACHE";
        bench set-config -g redis_queue "redis://$$REDIS_QUEUE";
        bench set-config -g redis_socketio "redis://$$REDIS_QUEUE";
        bench set-config -gp socketio_port $$SOCKETIO_PORT;
    environment:
      DB_HOST: "${DB_HOST:-db}"
      DB_PORT: "3306"
      REDIS_CACHE: redis-cache:6379
      REDIS_QUEUE: redis-queue:6379
      SOCKETIO_PORT: "9000"
      REGENERATE_APPS_TXT: "${REGENERATE_APPS_TXT:-0}"
    volumes:
      - sites:/home/frappe/frappe-bench/sites
    networks:
      - bench-network

  create-site:
    <<: *custom_image
    deploy:
      mode: replicated
      replicas: ${CREATE_SITE:-0}
      restart_policy:
        condition: none
    entrypoint: ["bash", "-c"]
    command:
      - >
        wait-for-it -t 120 $$DB_HOST:$$DB_PORT;
        wait-for-it -t 120 redis-cache:6379;
        wait-for-it -t 120 redis-queue:6379;
        export start=`date +%s`;
        until [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && \
          [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_cache // empty"` ]] && \
          [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_queue // empty"` ]];
        do
          echo "Waiting for sites/common_site_config.json to be created";
          sleep 5;
          if (( `date +%s`-start > 120 )); then
            echo "could not find sites/common_site_config.json with required keys";
            exit 1
          fi
        done;
        echo "sites/common_site_config.json found";
        [[ -d "sites/${SITE_NAME}" ]] && echo "${SITE_NAME} already exists" && exit 0;
        bench new-site --mariadb-user-host-login-scope='%' --admin-password=$${ADMIN_PASSWORD} --db-root-username=root --db-root-password=$${DB_ROOT_PASSWORD} $${INSTALL_APP_ARGS} $${SITE_NAME};
    volumes:
      - sites:/home/frappe/frappe-bench/sites
    environment:
      SITE_NAME: ${SITE_NAME}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      DB_HOST: ${DB_HOST:-db}
      DB_PORT: "${DB_PORT:-3306}"
      DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      INSTALL_APP_ARGS: ${INSTALL_APP_ARGS}
    networks:
      - bench-network

  migration:
    <<: *custom_image
    deploy:
      mode: replicated
      replicas: ${MIGRATE:-0}
      restart_policy:
        condition: none
    entrypoint: ["bash", "-c"]
    command:
      - >
        curl -f http://${SITE_NAME}:8080/api/method/ping || echo "Site busy" && exit 0;
        bench --site all set-config -p maintenance_mode 1;
        bench --site all set-config -p pause_scheduler 1;
        bench --site all migrate;
        bench --site all set-config -p maintenance_mode 0;
        bench --site all set-config -p pause_scheduler 0;
    volumes:
      - sites:/home/frappe/frappe-bench/sites
    networks:
      - bench-network

  db:
    image: mariadb:10.6
    deploy:
      mode: replicated
      replicas: ${ENABLE_DB:-0}
      restart_policy:
        condition: always
    healthcheck:
      test: mysqladmin ping -h localhost --password=${DB_ROOT_PASSWORD}
      interval: 1s
      retries: 20
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --skip-character-set-client-handshake
      - --skip-innodb-read-only-compressed
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
      - MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - bench-network

  redis-cache:
    deploy:
      restart_policy:
        condition: always
    image: redis:6.2-alpine
    volumes:
      - redis-cache-data:/data
    networks:
      - bench-network
    healthcheck:
      test:
        - CMD
        - redis-cli
        - ping
      interval: 5s
      timeout: 5s
      retries: 3

  redis-queue:
    deploy:
      restart_policy:
        condition: always
    image: redis:6.2-alpine
    volumes:
      - redis-queue-data:/data
    networks:
      - bench-network
    healthcheck:
      test:
        - CMD
        - redis-cli
        - ping
      interval: 5s
      timeout: 5s
      retries: 3

  redis-socketio:
    deploy:
      restart_policy:
        condition: always
    image: redis:6.2-alpine
    volumes:
      - redis-socketio-data:/data
    networks:
      - bench-network
    healthcheck:
      test:
        - CMD
        - redis-cli
        - ping
      interval: 5s
      timeout: 5s
      retries: 3

volumes:
  db-data:
  redis-cache-data:
  redis-queue-data:
  redis-socketio-data:
  sites:
    driver_opts:
      type: "${SITE_VOLUME_TYPE}"
      o: "${SITE_VOLUME_OPTS}"
      device: "${SITE_VOLUME_DEV}"

networks:
  bench-network: