caprover / one-click-apps

Community Maintained One Click Apps (https://github.com/caprover/caprover)
Apache License 2.0
561 stars 548 forks source link

App Suggestion: ERPNext #624

Open ak4zh opened 2 years ago

ak4zh commented 2 years ago

Please tell us what app you'd like to see on CapRover as a one-click app. Free and Open Source Enterprise Resource Planning (ERP)

Do you know if there is any official Docker image for the app? ERPNext Docker: https://github.com/frappe/frappe_docker

nirjhar commented 2 years ago

Any update???

supersume commented 2 years ago

Adding this would very much be appreciated

yusef-ho commented 2 years ago

+1

0x7466 commented 2 years ago

+1

matbgn commented 2 years ago

I will give it a shot in the next weeks. Any advice from your side @githubsaturn regarding the official compose file, before I start?

https://github.com/frappe/frappe_docker/blob/main/compose.yaml

githubsaturn commented 2 years ago

Two things that jumped out to me: 1- it uses YAML anchors, you just need to flatten them 2- it uses command, and you need to change to dockerfileLines.

nirjhar commented 2 years ago

In another note, can you guys ask source handlers of caprover to upgrade itself for a new release? Caprover itself very old. Sent from my iPhoneOn Nov 18, 2022, at 10:05 AM, Kasra Bigdeli @.***> wrote: Two things that jumped out to me: 1- it uses YAML anchors, you just need to flatten them 2- it uses command, and you need to change to dockerfileLines.

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>

irfanMiral commented 2 years ago

@matbgn is there any update? I tried a few crm but it seems erpnext fits best. but seems a bit confusing to install on caprover manually, should I wait for update if you are working on it?

nirjhar commented 1 year ago

ERP Next installation is not tough. I can help

On Thu, Nov 24, 2022 at 2:39 AM irfan Miral @.***> wrote:

@matbgn https://github.com/matbgn is there any update? I tried a few crm but it seems erpnext fits best. but seems a bit confusing to install on caprover manually, should I wait for update if you are working on it?

— Reply to this email directly, view it on GitHub https://github.com/caprover/one-click-apps/issues/624#issuecomment-1325633523, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKQ6OI5KWSSECTHF66JRPTWJZ6HBANCNFSM5OIHKQWA . You are receiving this because you commented.Message ID: @.***>

irfanMiral commented 1 year ago

I checked single server instructions and installation has been done via github clone, not docker repo (plus latest version on docker is 13) and there is proxy manager inside docker etc, as I understood I only need erpnext, erpnext-db(mariadb) and erpnext-worker containers on caprover.

WEBzaytsev commented 1 year ago

+1

matbgn commented 1 year ago

Just for information I'm planing to tackle this most likely on week commencing on 26th December. As always, if anyone is willing to take responsibility of this in the mean time, please feel free.

mathiasfoster commented 1 year ago

+1 also

matbgn commented 1 year ago

Considering the complexity of the configured ERPNext final file ( https://github.com/frappe/frappe_docker/blob/main/pwd.yml ) and the time I'm able to invest right now I will postpone this deployment to an undefined date.

name: frappe_docker
services:
  backend:
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/erpnext:v14.13.0
    networks:
      default: null
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
  configurator:
    command:
    - |
      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_SOCKETIO"; bench set-config -gp socketio_port $$SOCKETIO_PORT;
    depends_on:
      db:
        condition: service_started
      redis-cache:
        condition: service_started
      redis-queue:
        condition: service_started
      redis-socketio:
        condition: service_started
    entrypoint:
    - bash
    - -c
    environment:
      DB_HOST: db
      DB_PORT: "5432"
      REDIS_CACHE: redis-cache:6379
      REDIS_QUEUE: redis-queue:6379
      REDIS_SOCKETIO: redis-socketio:6379
      SOCKETIO_PORT: "9000"
    image: frappe/erpnext:v14.13.0
    networks:
      default: null
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
  db:
    command: []
    environment:
      POSTGRES_PASSWORD: "123"
    image: postgres:13.5
    networks:
      default: null
    volumes:
    - type: volume
      source: db-data
      target: /var/lib/postgresql
      volume: {}
  frontend:
    command:
    - nginx-entrypoint.sh
    depends_on:
      backend:
        condition: service_started
      websocket:
        condition: service_started
    environment:
      BACKEND: backend:8000
      CLIENT_MAX_BODY_SIZE: 50m
      FRAPPE_SITE_NAME_HEADER: $$host
      PROXY_READ_TIMOUT: "120"
      SOCKETIO: websocket:9000
      UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
      UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
      UPSTREAM_REAL_IP_RECURSIVE: "off"
    image: frappe/erpnext:v14.13.0
    labels:
      traefik.enable: "true"
      traefik.http.routers.frontend-http.entrypoints: web
      traefik.http.routers.frontend-http.rule: HostRegexp(`{any:.+}`)
      traefik.http.services.frontend.loadbalancer.server.port: "8080"
    networks:
      default: null
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
  proxy:
    command:
    - --providers.docker
    - --providers.docker.exposedbydefault=false
    - --entrypoints.web.address=:80
    image: traefik:2.5
    networks:
      default: null
    ports:
    - mode: ingress
      target: 80
      published: "80"
      protocol: tcp
    userns_mode: host
    volumes:
    - type: bind
      source: /var/run/docker.sock
      target: /var/run/docker.sock
      read_only: true
      bind:
        create_host_path: true
  queue-default:
    command:
    - bench
    - worker
    - --queue
    - default
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/erpnext:v14.13.0
    networks:
      default: null
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
  queue-long:
    command:
    - bench
    - worker
    - --queue
    - long
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/erpnext:v14.13.0
    networks:
      default: null
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
  queue-short:
    command:
    - bench
    - worker
    - --queue
    - short
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/erpnext:v14.13.0
    networks:
      default: null
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
  redis-cache:
    image: redis:6.2-alpine
    networks:
      default: null
    volumes:
    - type: volume
      source: redis-cache-data
      target: /data
      volume: {}
  redis-queue:
    image: redis:6.2-alpine
    networks:
      default: null
    volumes:
    - type: volume
      source: redis-queue-data
      target: /data
      volume: {}
  redis-socketio:
    image: redis:6.2-alpine
    networks:
      default: null
    volumes:
    - type: volume
      source: redis-socketio-data
      target: /data
      volume: {}
  scheduler:
    command:
    - bench
    - schedule
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/erpnext:v14.13.0
    networks:
      default: null
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
  websocket:
    command:
    - node
    - /home/frappe/frappe-bench/apps/frappe/socketio.js
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/erpnext:v14.13.0
    networks:
      default: null
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
networks:
  default:
    name: frappe_docker_default
volumes:
  db-data:
    name: frappe_docker_db-data
  redis-cache-data:
    name: frappe_docker_redis-cache-data
  redis-queue-data:
    name: frappe_docker_redis-queue-data
  redis-socketio-data:
    name: frappe_docker_redis-socketio-data
  sites:
    name: frappe_docker_sites
x-backend-defaults:
  depends_on:
    configurator:
      condition: service_completed_successfully
  image: frappe/erpnext:v14.13.0
  volumes:
  - sites:/home/frappe/frappe-bench/sites
x-depends-on-configurator:
  depends_on:
    configurator:
      condition: service_completed_successfully
matbgn commented 1 year ago

Started working on the ERPNext implementation, but as expected it's not that obvious...

Any input will be appreciated, e.g. from @githubsaturn ;-)

Our current work is replicated here: https://github.com/matbgn/one-click-apps/blob/feat/add-erpnext/matbgn/public/v4/apps/erpnext.yml

Status: Frontend won't deploy and logs are not explecit or even locatable

Here is our delete script to destroy the app via API for testing purposes:

#!/usr/bin/env bash
APPNAME="erp-test"

function drop {
    app="${1}"
    volumes="${2}"
    echo "--------------------------------------------------------"
    echo "Deleting ${app}"
    echo "--------------------------------------------------------"
    JSON='{ "appName": "'"${app}"'", "volumes":['"${volumes}"'] }'
    # First call the API (/user/apps/appDefinitions/update endpoint) and set the instanceCount to 0, then attempt to delete. Doing so, will result in more reliable deletion of the volumes.
    # https://github.com/caprover/caprover/issues/1235  
    caprover api \
        -n "SERVER_NAME_REDACTED" \
        -p "PASSWORD_REDACTED" \
        -t /user/apps/appDefinitions/update \
        -m POST -d '{ "appName": "'"${app}"'", "instanceCount": "0"}'
    caprover api \
        -n "SERVER_NAME_REDACTED" \
        -p "PASSWORD_REDACTED" \
        -t /user/apps/appDefinitions/delete \
        -m POST -d "${JSON}"
}

drop "${APPNAME}-configurator" ''
drop "${APPNAME}-create-site" ''
drop "${APPNAME}-frontend" ''
drop "${APPNAME}-queue-default" ''
drop "${APPNAME}-queue-long" ''
drop "${APPNAME}-queue-short" ''
drop "${APPNAME}-scheduler" ''
drop "${APPNAME}-websocket" ''

drop "${APPNAME}-redis-queue" '"'"${APPNAME}"'-redis-queue"'
drop "${APPNAME}-redis-cache" '"'"${APPNAME}"'-redis-cache"'
drop "${APPNAME}-redis-socketio" '"'"${APPNAME}"'-redis-socketio"'
drop "${APPNAME}-db" '"'"${APPNAME}"'-db"'

# Delete multiple volumes at once
# https://github.com/caprover/one-click-apps/issues/491#issuecomment-951985921
drop "${APPNAME}-backend" '"'"${APPNAME}"'-sites","'"${APPNAME}"'-logs"'
githubsaturn commented 1 year ago

yea this app is super complex. I suggest you start with a Docker compose and make it work, then move to CapRover.

Another thing that could help is to avoid having complex CMD lines, and just write a script in github gist and use ADD to pull it into the image. Here is an example: https://github.com/caprover/one-click-apps/blob/0a80f8e9e756d04896d531a39506f1523462a6fa/public/v4/apps/rsync-looped.yml#L6-L11

matbgn commented 1 year ago

Of course I tested it locally with docker compose ;-)

I tried the ADD trick, but unfortunately was not able to get it to work with the frappe custom image (shame on me for that particular point).

Honestly, I gave up, then I installed it in it's own VM and have to admit that there is no real way for Caprover to handle it. The complexity of its architecture is much more challenging than other types of applications. For example, adding modules like HR and so on after the core installation (https://github.com/frappe/frappe_docker/issues/959#issuecomment-1279121637).

After, my relative experience with Caprover in production for a year now, I definitely suggest to close this issue as not decently solvable for both perspective: technical and Caprover user happiness (no way to support such a jungle in long term).

MaxMorais commented 2 months ago

Hi @matbgn I got ERPNext working and installed on my caprover!

Off course, my approach is far from perfect, but here goes!

The base64 encoded things, are fck uggly, but was the unique way to get it working outside a github repository!

captainVersion: 4
caproverOneClickApp:
  displayName: Frappe and/or ERPNext
  isOfficial: true
  description: Frappe and/or ERPNext installation
  documentation: Nothing to say right now
  variables:
    - id: $$cap_USER_EMAIL
      label: Your User Email
    - id: $$cap_USER_PASSWORD
      label: Your User Password
      defaultValue: $$cap_gen_random_hex(16)
    - id: $$cap_ADMINISTRATOR_PASSWORD
      label: Tenant Administrator Password
      defaultValue: $$cap_gen_random_hex(16)
    - id: $$cap_APP_TYPE
      label: Installation Type
      description: (frappe|erpnext)
      defaultValue: erpnext
      validRegex: /^(frappe|erpnext)$/
    - id: $$cap_APP_VERSION
      label: Installation Version
      description: "Frappe / ERPNext version (eg: v15)"
      defaultValue: v15
    - id: $$cap_DB_HOST
      label: "Mariadb Host"
      defaultValue: srv-captain--mariadb-db
    - id: $$cap_DB_PORT
      label: "Mariadb Port"
      defaultValue: "3306"
    - id: $$cap_DB_ROOT_USER
      label: Mariadb ROOT User
      defaultValue: root
    - id: $$cap_DB_ROOT_PASSWORD
      label: Mariadb ROOT Password
      defaultValue: $$cap_gen_random_hex(16)
    - id: $$cap_SOCKETIO_PORT
      label: Socketio PORT
      defaultValue: "9000"
      validRegex: /^([0-9]+)/
    - id: $$cap_BACKEND_PORT
      label: Backend PORT
      defaultValue: "8000"
      validRegex: /^([0-9]+)/
    - id: $$cap_UPSTREAM_REAL_IP_ADDRESS
      label: Nginx Upstream Real IP Address
      defaultValue: 127.0.0.1
      description: Usually, it's the public IP of your server
    - id: $$cap_UPSTREAM_REAL_IP_HEADER
      label: Nginx Upstream Real IP Header
      defaultValue: X-Forwarded-For
    - id: $$cap_UPSTREAM_IP_RECURSIVE
      label: Nginx Upstream IP Recursive
      defaultValue: "true"
    - id: $$cap_PROXY_READ_TIMEOUT
      label: Nginx Proxy Read Timeout
      defaultValue: "120"
    - id: $$cap_CLIENT_MAX_BODY_SIZE
      label: Nginx Client Max Body Size
      defaultValue: 50m      
  instructions: >-
    start: |-
      This is a all-in-one Captain Template and will deploy all services 
      needed for ERPNext or Frappe execution environment.

      In total this template will launch 11 containers

      2 Redis Instances             - OK if Running
      1 Mariadb Instance            - OK if Running
      1 Backend Service             - OK if Running
      1 Frontend Service            - OK if Running
      2 Worker Services             - OK if Running
      1 Scheduler Service           - OK if Running
      1 Socketio Service            - OK if Running

      1 Configurator Container      - OK if DEAD
      1 Site Creator                - OK if DEAD

    end: |-
      We launched 11 containers, to launch ERPNext/Frappe

      Your ERPNext should be accessible at http://$cap_appname.$$cap_root_domain

      Credentials:
        | Role       | Username                             | Password | 
        +------------+--------------------------------------+----------|
        |Admin       | Administrator                        | $$cap_ADMIN_PASSWORD |
        |Sys Manager | $$cap_USER_EMAIL                     | $$cap_USER_PASSWORD  |

      You should allways keep those services running 
        to maintain the healthy of ERPNext/Frappe Services

      | Service          |Purpose             |Internal Host |
      +------------------+--------------------+--------------+
      | Redis            | Cache              | srv-captain--$$cap_appname-redis-cache |
      | Redis            | Background Queue   | srv-captain--$$cap_appname-redis-queue |
      | Mariadb          | Database           | srv-captain--$$cap_appname-db |
      | Backend          | Application        | srv-captain--$$cap_appname-backend |
      | Frontend         | Nginx Proxy        | srv-captain--$$cap_appname-frontend |
      | Socketio         | WebSocket          | srv-captain--$$cap_appname-websocket |
      | Worker           | Background Consumer| srv-captain--$$cap_appname-queue-short |
      | Worker           | Background Consumer| srv-captain--$$cap_appname-queue-long |
      | Scheduler        | Background Trigger | srv-captain--$$cap_appname-scheduler |

      Additionally to those services, we launched also 2 additional containers
        that surelly ca be delete, they are

      | Service          |Purpose             |Internal Host |
      +------------------+--------------------+--------------+
      | Configurator     | Define Settings    | $$cap_appname-configurator |
      | Site-Creator     | Launch             | $$cap_appname-site-creator |
x-customizable-image:
  image: frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
x-depends-on-configurator:
  depends_on:
    configurator:
      condition: service_completed_successfully
x-sites-volume:
  volumes:
    - $$cap_appname-sites:/home/frappe/frappe-bench/sites
    - $$cap_appname-logs:/home/frappe/frappe-bench/logs
x-backend-defaults:
  depends_on:
    configurator:
      condition: service_completed_successfully
  image: frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
  volumes:
    - $$cap_appname-sites:/home/frappe/frappe-bench/sites
    - $$cap_appname-logs:/home/frappe/frappe-bench/logs
x-redis-defaults:
  caproverExtra:
    notExposeAsWebApp: true
  image: redis:6.2-alpine
  deploy:
    restart_condition:
      condition: on-failure
services:
  $$cap_appname-redis-queue:
    caproverExtra:
      notExposeAsWebApp: true
    image: redis:6.2-alpine
    deploy:
      restart_condition:
        condition: on-failure
    volumes:
      - $$cap_appname-redis-queue-data:/data
  $$cap_appname-redis-cache:
    caproverExtra:
      notExposeAsWebApp: true
    image: redis:6.2-alpine
    deploy:
      restart_condition:
        condition: on-failure
    volumes:
      - $$cap_appname-redis-cache-data:/data
  $$cap_appname-configurator:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["bash", "-c", "echo \"ZWNobyAiU3RhcnRpbmcgY29uZmlndXJhdGlvbiI7CmxzIC0xIGFwcHMgPiBzaXRlcy9hcHBzLnR4dDsKZWNobyAiQXBwcyBDb25maWd1cmVkIjsKYmVuY2ggc2V0LWNvbmZpZyAtZyBkYl9ob3N0ICREQl9IT1NUOwpiZW5jaCBzZXQtY29uZmlnIC1ncCBkYl9wb3J0ICREQl9QT1JUOwplY2hvICJEQiBIb3N0OlBvcnQgc2V0IHRvICREQl9IT1NUOiREQl9QT1JUIjsKYmVuY2ggc2V0LWNvbmZpZyAtZyByZWRpc19jYWNoZSAicmVkaXM6Ly8kUkVESVNfQ0FDSEUiOwplY2hvICJSZWRpcyBRdWV1ZSBzZXQgdG8gJFJFRElTX0NBQ0hFIjsKYmVuY2ggc2V0LWNvbmZpZyAtZyByZWRpc19xdWV1ZSAicmVkaXM6Ly8kUkVESVNfUVVFVUUiOwplY2hvICJSZWRpcyBDYWNoZSBzZXQgdG8gJFJFRElTX0NBQ0hFIjsKYmVuY2ggc2V0LWNvbmZpZyAtZyByZWRpc19zb2NrZXRpbyAicmVkaXM6Ly8kUkVESVNfUVVFVUUiOwplY2hvICJSZWRpcyBTb2NrZXRpbyBzZXQgdG8gJFJFRElTX1FVRVVFIgpiZW5jaCBzZXQtY29uZmlnIC1ncCBzb2NrZXRpb19wb3J0ICRTT0NLRVRJT19QT1JUOwplY2hvICJTb2NrZXRpbyBQb3J0IHNldCB0byAkU09DS0VUSU9fUE9SVCI7CmV4aXQgMDs=\"
          | base64 -d | sh"]
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    platform: linux/amd64
    environment:
      #DB_HOST: srv-captain--$$cap_appname-db
      #DB_PORT: "3306"
      DB_HOST: $$cap_DB_HOST
      DB_PORT: $$cap_DB_PORT
      DB_ROOT_USER: $$cap_DB_ROOT_USER
      DB_ROOT_PASSWORD: $$cap_DB_ROOT_PASSWORD
      REDIS_CACHE: srv-captain--$$cap_appname-redis-cache:6379
      REDIS_QUEUE: srv-captain--$$cap_appname-redis-queue:6379
      SOCKETIO_PORT: $$cap_SOCKETIO_PORT
  $$cap_appname-backend:
    caproverExtra:
      notExposeAsWebApp: true
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    platform: linux/amd64
  $$cap_appname:
    caproverExtra:
      containerHttpPort: $$cap_BACKEND_PORT
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["bash", "-c", "echo
          \"IyEvYmluL2Jhc2gKCiMgU2V0IHZhcmlhYmxlcyB0aGF0IGRvIG5vdCBleGlzdAppZiBbWyAteiAiJEJBQ0tFTkQiIF1dOyB0aGVuCiAgZWNobyAiQkFDS0VORCBkZWZhdWx0aW5nIHRvIDAuMC4wLjA6ODAwMCIKICBleHBvcnQgQkFDS0VORD0wLjAuMC4wOjgwMDAKZmkKaWYgW1sgLXogIiRTT0NLRVRJTyIgXV07IHRoZW4KICBlY2hvICJTT0NLRVRJTyBkZWZhdWx0aW5nIHRvIDAuMC4wLjA6OTAwMCIKICBleHBvcnQgU09DS0VUSU89MC4wLjAuMDo5MDAwCmZpCmlmIFtbIC16ICIkVVBTVFJFQU1fUkVBTF9JUF9BRERSRVNTIiBdXTsgdGhlbgogIGVjaG8gIlVQU1RSRUFNX1JFQUxfSVBfQUREUkVTUyBkZWZhdWx0aW5nIHRvIDEyNy4wLjAuMSIKICBleHBvcnQgVVBTVFJFQU1fUkVBTF9JUF9BRERSRVNTPTEyNy4wLjAuMQpmaQppZiBbWyAteiAiJFVQU1RSRUFNX1JFQUxfSVBfSEVBREVSIiBdXTsgdGhlbgogIGVjaG8gIlVQU1RSRUFNX1JFQUxfSVBfSEVBREVSIGRlZmF1bHRpbmcgdG8gWC1Gb3J3YXJkZWQtRm9yIgogIGV4cG9ydCBVUFNUUkVBTV9SRUFMX0lQX0hFQURFUj1YLUZvcndhcmRlZC1Gb3IKZmkKaWYgW1sgLXogIiRVUFNUUkVBTV9SRUFMX0lQX1JFQ1VSU0lWRSIgXV07IHRoZW4KICBlY2hvICJVUFNUUkVBTV9SRUFMX0lQX1JFQ1VSU0lWRSBkZWZhdWx0aW5nIHRvIG9mZiIKICBleHBvcnQgVVBTVFJFQU1fUkVBTF9JUF9SRUNVUlNJVkU9b2ZmCmZpCmlmIFtbIC16ICIkRlJBUFBFX1NJVEVfTkFNRV9IRUFERVIiIF1dOyB0aGVuCiAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDE2CiAgZWNobyAnRlJBUFBFX1NJVEVfTkFNRV9IRUFERVIgZGVmYXVsdGluZyB0byAkaG9zdCcKICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwMTYKICBleHBvcnQgRlJBUFBFX1NJVEVfTkFNRV9IRUFERVI9JyRob3N0JwpmaQoKaWYgW1sgLXogIiRQUk9YWV9SRUFEX1RJTUVPVVQiIF1dOyB0aGVuCiAgZWNobyAiUFJPWFlfUkVBRF9USU1FT1VUIGRlZmF1bHRpbmcgdG8gMTIwIgogIGV4cG9ydCBQUk9YWV9SRUFEX1RJTUVPVVQ9MTIwCmZpCgppZiBbWyAteiAiJENMSUVOVF9NQVhfQk9EWV9TSVpFIiBdXTsgdGhlbgogIGVjaG8gIkNMSUVOVF9NQVhfQk9EWV9TSVpFIGRlZmF1bHRpbmcgdG8gNTBtIgogIGV4cG9ydCBDTElFTlRfTUFYX0JPRFlfU0laRT01MG0KZmkKCiMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjAxNgplbnZzdWJzdCAnJHtCQUNLRU5EfQogICR7U09DS0VUSU99CiAgJHtVUFNUUkVBTV9SRUFMX0lQX0FERFJFU1N9CiAgJHtVUFNUUkVBTV9SRUFMX0lQX0hFQURFUn0KICAke1VQU1RSRUFNX1JFQUxfSVBfUkVDVVJTSVZFfQogICR7RlJBUFBFX1NJVEVfTkFNRV9IRUFERVJ9CiAgJHtQUk9YWV9SRUFEX1RJTUVPVVR9Cgkke0NMSUVOVF9NQVhfQk9EWV9TSVpFfScgXAogIDwvdGVtcGxhdGVzL25naW54L2ZyYXBwZS5jb25mLnRlbXBsYXRlID4vZXRjL25naW54L2NvbmYuZC9mcmFwcGUuY29uZgoKbmdpbnggLWcgJ2RhZW1vbiBvZmY7Jw==\"
          | base64 -d | bash"]
    depends_on:
      - $$cap_appname-backend
      - $$cap_appname-websocket
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    environment:
      BACKEND: srv-captain--$$cap_appname-backend:$$cap_BACKEND_PORT
      SOCKETIO: srv-captain--$$cap_appname-websocket:$$cap_SOCKETIO_PORT
      FRAPPE_SITE_NAME_HEADER: $$cap_appname.$$cap_root_domain
      UPSTREAM_REAL_IP_ADDRESS: $$cap_UPSTREAM_REAL_IP_ADDRESS
      UPSTREAM_IP_HEADER: $$cap_UPSTREAM_REAL_IP_HEADER
      UPSTREAM_IP_RECURSIVE: $$cap_UPSTREAM_IP_RECURSIVE
      PROXY_READ_TIMEOUT: $$cap_PROXY_READ_TIMEOUT
      CLIENT_MAX_BODY_SIZE: $$cap_CLIENT_MAX_BODY_SIZE
  $$cap_appname-websocket:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["node", "/home/frappe/frappe-bench/apps/frappe/socketio.js"]
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    environment:
      FRAPPE_SITE: $$cap_appname.$$cap_root_domain
      FRAPPE_REDIS_CACHE: redis://srv-captain--$$cap_appname-redis-cache:6379
      FRAPPE_REDIS_QUEUE: redis://srv-captain--$$cap_appname-redis-queue:6379
      FRAPPE_SOCKETIO_PORT: $$cap_SOCKETIO_PORT
    platform: linux/amd64
  $$cap_appname-queue-short:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["bench", "worker", "--queue", "short,default"]
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
  $$cap_appname-queue-long:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["bench", "worker", "--queue", "long,default,short"]
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
  $$cap_appname-scheduler:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["bench", "scheduler"]
    platform: linux/amd64
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
  $$cap_appname-site-creator:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["bash", "-c", "echo
          \"d2FpdC1mb3ItaXQgLXQgMTIwICREQl9IT1NUOiREQl9QT1JUOwp3YWl0LWZvci1pdCAtdCAxMjAgJFJFRElTX0NBQ0hFOwp3YWl0LWZvci1pdCAtdCAxMjAgJFJFRElTX1NPQ0tFVElPOwp3YWl0LWZvci1pdCAtdCAxMjAgJFJFRElTX1FVRVVFOwplY2hvICIkKGxzIC0xIHNpdGVzKSI7CmV4cG9ydCBzdGFydD1gZGF0ZSArJXNgOwp1bnRpbCBbWyAtbiBgZ3JlcCAtaHMgXiBzaXRlcy9jb21tb25fc2l0ZV9jb25maWcuanNvbiB8IGpxIC1yICIuZGJfaG9zdCAvLyBlbXB0eSJgIF1dICYmIFwKICAgW1sgLW4gYGdyZXAgLWhzIF4gc2l0ZXMvY29tbW9uX3NpdGVfY29uZmlnLmpzb24gfCBqcSAtciAiLnJlZGlzX2NhY2hlIC8vIGVtcHR5ImAgXV0gJiYgXAogICBbWyAtbiBgZ3JlcCAtaHMgXiBzaXRlcy9jb21tb25fc2l0ZV9jb25maWcuanNvbiB8IGpxIC1yICIucmVkaXNfcXVldWUgLy8gZW1wdHkiYCBdXTsKZG8KICBlY2hvICJXYWl0aW5nIGZvciBzaXRlcy9jb21tb25fc2l0ZV9jb25maWcuanNvbiB0byBiZSBjcmVhdGVkIjsKICBzbGVlcCA1OwogIGlmICgoIGBkYXRlICslc2Atc3RhcnQgPiAxMjAgKSk7IHRoZW4KICAgIGVjaG8gImNvdWxkIG5vdCBmaW5kIHNpdGVzL2NvbW1vbl9zaXRlX2NvbmZpZy5qc29uIHdpdGggcmVxdWlyZWQga2V5cyI7CiAgICBleGl0IDEKICBmaQpkb25lOwplY2hvICJzaXRlcy9jb21tb25fc2l0ZV9jb25maWcuanNvbiBmb3VuZCI7CmlmIFsgISAtZCAic2l0ZXMvJFNJVEUiIF07IHRoZW4KICBlY2hvICJSZWFkeSB0byBjcmVhdGUgJFNJVEUiOwogIGJlbmNoIG5ldy1zaXRlIC0tbm8tbWFyaWFkYi1zb2NrZXQgLS1kYi1yb290LXVzZXJuYW1lPSREQl9ST09UX1VTRVIgLS1kYi1yb290LXBhc3N3b3JkPSREQl9ST09UX1BBU1NXT1JEIC0tYWRtaW4tcGFzc3dvcmQ9JEFETUlOSVNUUkFUT1JfUEFTU1dPUkQgLS1pbnN0YWxsLWFwcCBlcnBuZXh0IC0tc2V0LWRlZmF1bHQgJFNJVEUgLS1mb3JjZTsKICBiZW5jaCBhZGQtc3lzdGVtLW1hbmFnZXIgLS1lbWFpbD0kVVNFUl9FTUFJTCAtLXBhc3N3b3JkPSRVU0VSX1BBU1NXT1JEOwogIGJlbmNoIHNjaGVkdWxlciBlbmFibGU7CmZpOwplY2hvICJOZXcgc2l0ZSAkU0lURSBjcmVhdGVkIHN1Y2Vzc2Z1bGx5ISI7\"
          | base64 -d | bash"]
    platform: linux/amd64
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    environment:
      DB_HOST: $$cap_DB_HOST
      DB_PORT: $$cap_DB_PORT
      DB_ROOT_USER: $$cap_DB_ROOT_USER
      DB_ROOT_PASSWORD: $$cap_DB_ROOT_PASSWORD
      REDIS_CACHE: srv-captain--$$cap_appname-redis-cache:6379
      REDIS_QUEUE: srv-captain--$$cap_appname-redis-queue:6379
      REDIS_SOCKETIO: srv-captain--$$cap_appname-redis-queue:6379
      ADMINISTRATOR_PASSWORD: $$cap_ADMINISTRATOR_PASSWORD
      SITE: $$cap_appname.$$cap_root_domain
      USER_EMAIL: $$cap_USER_EMAIL
      USER_PASSWORD: $$cap_USER_PASSWORD
volumes:
  $$cap_appname-db-data: null
  $$cap_appname-sites: null
  $$cap_appname-logs: null
  $$cap_appname-redis-queue-data: null
  $$cap_appname-redis-cache-data: null
githubsaturn commented 2 months ago

Definitely a clever way! But you can certainly improve this a bit.

Just do something like

FROM something
RUN echo "bench set-config -g db_host $DB_HOST; something; something" > startup.sh
CMD ["bash", "-c", "./startup.sh"]

It'll be a lot more readable

MaxMorais commented 2 months ago

@githubsaturn, for some scripts, like the one, you mention, for sure can be done!

But the other 2, with while and if blocks, did not will work that way!

I tried for about 5 days, before I came with that alternative, if you have an idea, about how make that work with while and if blocks, I'm glad to hear!

githubsaturn commented 2 months ago

Try this:

caproverExtra:
  dockerfileLines:
    - 'FROM ubuntu:18.04'
    - '# Create a multi-line startup.sh script during the image build'
    - 'RUN echo ''#!/bin/bash'' > /startup.sh     && cat >> /startup.sh <<''EOF'''
    - echo "Starting up..."
    - '# Add more configuration or startup commands here'
    - echo "Configuration complete."
    - EOF
    - '# Make the script executable'
    - RUN chmod +x /startup.sh
    - 'CMD ["/startup.sh"]'
MaxMorais commented 5 days ago

Hi guys!

After a while I update the script!

captainVersion: 4
caproverOneClickApp:
  displayName: Frappe and/or ERPNext
  isOfficial: true
  description: Frappe and/or ERPNext installation
  documentation: Nothing to say right now
  variables:
    - id: $$cap_USER_EMAIL
      label: Your User Email
    - id: $$cap_USER_PASSWORD
      label: Your User Password
      defaultValue: $$cap_gen_random_hex(16)
    - id: $$cap_ADMINISTRATOR_PASSWORD
      label: Tenant Administrator Password
      defaultValue: $$cap_gen_random_hex(16)
    - id: $$cap_APP_TYPE
      label: Installation Type
      description: (frappe|erpnext)
      defaultValue: erpnext
      validRegex: /^(frappe|erpnext)$/
    - id: $$cap_APP_VERSION
      label: Installation Version
      description: "Frappe / ERPNext version (eg: version-15)"
      defaultValue: v15
    - id: $$cap_DB_HOST
      label: "Mariadb Host"
      defaultValue: srv-captain--mariadb-db
    - id: $$cap_DB_PORT
      label: "Mariadb Port"
      defaultValue: "3306"
    - id: $$cap_DB_ROOT_USER
      label: Mariadb ROOT User
      defaultValue: root
    - id: $$cap_DB_ROOT_PASSWORD
      label: Mariadb ROOT Password
      defaultValue: 3u-S0u-1-Gr@nd3-Cod3r
    - id: $$cap_SOCKETIO_PORT
      label: Socketio PORT
      defaultValue: "9000"
      validRegex: /^([0-9]+)/
    - id: $$cap_BACKEND_PORT
      label: Backend PORT
      defaultValue: "8000"
      validRegex: /^([0-9]+)/
    - id: $$cap_UPSTREAM_REAL_IP_ADDRESS
      label: Nginx Upstream Real IP Address
      defaultValue: 127.0.0.1
      description: Usually, it's the public IP of your server
    - id: $$cap_UPSTREAM_REAL_IP_HEADER
      label: Nginx Upstream Real IP Header
      defaultValue: X-Forwarded-For
    - id: $$cap_UPSTREAM_IP_RECURSIVE
      label: Nginx Upstream IP Recursive
      defaultValue: "true"
    - id: $$cap_PROXY_READ_TIMEOUT
      label: Nginx Proxy Read Timeout
      defaultValue: "120"
    - id: $$cap_CLIENT_MAX_BODY_SIZE
      label: Nginx Client Max Body Size
      defaultValue: 50m      
  instructions: >-
    start: |-
      This is a all-in-one Captain Template and will deploy all services 
      needed for ERPNext or Frappe execution environment.

      In total this template will launch 11 containers

      2 Redis Instances             - OK if Running
      1 Mariadb Instance            - OK if Running
      1 Backend Service             - OK if Running
      1 Frontend Service            - OK if Running
      2 Worker Services             - OK if Running
      1 Scheduler Service           - OK if Running
      1 Socketio Service            - OK if Running

      1 Configurator Container      - OK if DEAD
      1 Site Creator        - OK if DEAD

    end: |-
      We launched 11 containers, to launch ERPNext/Frappe

      Your ERPNext should be accessible at http://$cap_appname.$$cap_root_domain

      Credentials:
        | Role       | Username                     | Password | 
        +------------+--------------------------------------+----------|
        |Admin       | Administrator                | $$cap_ADMIN_PASSWORD |
        |Sys Manager | $$cap_USER_EMAIL             | $$cap_USER_PASSWORD  |

      You should allways keep those services running 
        to maintain the healthy of ERPNext/Frappe Services

      | Service          |Purpose             |Internal Host |
      +------------------+--------------------+--------------+
      | Redis            | Cache              | srv-captain--$$cap_appname-redis-cache |
      | Redis            | Background Queue   | srv-captain--$$cap_appname-redis-queue |
      | Mariadb          | Database           | srv-captain--$$cap_appname-db          |
      | Backend          | Application        | srv-captain--$$cap_appname-backend     |
      | Frontend         | Nginx Proxy        | srv-captain--$$cap_appname-frontend    |
      | Socketio         | WebSocket          | srv-captain--$$cap_appname-websocket   |
      | Worker           | Background Consumer| srv-captain--$$cap_appname-queue-short |
      | Worker           | Background Consumer| srv-captain--$$cap_appname-queue-long  |
      | Scheduler        | Background Trigger | srv-captain--$$cap_appname-scheduler   |

      Additionally to those services, we launched also 2 additional containers
        that surelly ca be delete, they are

      | Service          |Purpose             |Internal Host |
      +------------------+--------------------+--------------+
      | Configurator     | Define Settings    | $$cap_appname-configurator |
      | Site-Creator     | Launch             | $$cap_appname-site-creator |
x-customizable-image:
  image: frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
x-depends-on-configurator:
  depends_on:
    configurator:
      condition: service_completed_successfully
x-sites-volume:
  volumes:
    - $$cap_appname-sites:/home/frappe/frappe-bench/sites
    - $$cap_appname-logs:/home/frappe/frappe-bench/logs
x-backend-defaults:
  depends_on:
    configurator:
      condition: service_completed_successfully
  image: frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
  volumes:
    - $$cap_appname-sites:/home/frappe/frappe-bench/sites
    - $$cap_appname-logs:/home/frappe/frappe-bench/logs
x-redis-defaults:
  caproverExtra:
    notExposeAsWebApp: true
  image: redis:6.2-alpine
  deploy:
    restart_condition:
      condition: on-failure
services:
  $$cap_appname-redis-queue:
    caproverExtra:
      notExposeAsWebApp: true
    image: redis:6.2-alpine
    deploy:
      restart_condition:
        condition: on-failure
    volumes:
      - $$cap_appname-redis-queue-data:/data
  $$cap_appname-redis-cache:
    caproverExtra:
      notExposeAsWebApp: true
    image: redis:6.2-alpine
    deploy:
      restart_condition:
        condition: on-failure
    volumes:
      - $$cap_appname-redis-cache-data:/data

  $$cap_appname-configurator:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - 'FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION'
        - '# Create a multi-line startup.sh script during image build'
        - 'RUN echo ''#/bin/bash'' > startup.sh && cat >> startup.sh <<''EOF'''
        - echo "Starting configuration";
        - ls -1 apps > sites/apps.txt;
        - echo "Apps Configured";
        - bench set-config -g db_host $DB_HOST;
        - bench set-config -gp db_port $DB_PORT;
        - echo "DB Host:Port set to $DB_HOST:$DB_PORT";
        - bench set-config -g redis_cache "redis://$REDIS_CACHE";
        - echo "Redis Queue set to $REDIS_CACHE";
        - bench set-config -g redis_queue "redis://$REDIS_QUEUE";
        - echo "Redis Cache set to $REDIS_CACHE";
        - bench set-config -g redis_socketio "redis://$REDIS_QUEUE";
        - echo "Redis Socketio set to $REDIS_QUEUE";
        - bench set-config -gp socketio_port $SOCKETIO_PORT;
        - echo "Socketio Port set to $SOCKETIO_PORT";
        - echo "Configuration complete";
        - exit 0;
        - EOF
        - '# Make the script executable'
        - RUN chmod a+x startup.sh
        - 'CMD ["startup.sh"]'

    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    platform: linux/amd64
    environment:
      #DB_HOST: srv-captain--$$cap_appname-db
      #DB_PORT: "3306"
      DB_HOST: $$cap_DB_HOST
      DB_PORT: $$cap_DB_PORT
      DB_ROOT_USER: $$cap_DB_ROOT_USER
      DB_ROOT_PASSWORD: $$cap_DB_ROOT_PASSWORD
      REDIS_CACHE: srv-captain--$$cap_appname-redis-cache:6379
      REDIS_QUEUE: srv-captain--$$cap_appname-redis-queue:6379
      SOCKETIO_PORT: $$cap_SOCKETIO_PORT
  $$cap_appname-backend:
    caproverExtra:
      notExposeAsWebApp: true
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    platform: linux/amd64
  $$cap_appname:
    caproverExtra:
      containerHttpPort: $$cap_BACKEND_PORT
      dockerfileLines:
        - 'FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION'
        - '# Create a multi-line startup.sh script during image build'
        - 'RUN echo ''#/bin/bash'' > startup.sh && cat >> startup.sh <<''EOF'''
        - '#!/bin/bash'
        - ''
        - '# Set variables that do not exist'
        - 'if [[ -z "\$BACKEND" ]]; then'
        - '   echo "BACKEND defaulting to 0.0.0.0:8000"'
        - '   export BACKEND=0.0.0.0:8000'
        - 'fi'
        - ''
        - 'if [[ -z "\$SOCKETIO" ]]; then'
        - '  echo "SOCKETIO defaulting to 0.0.0.0:9000"'
        - '  export SOCKETIO=0.0.0.0:9000'
        - 'fi'
        - ''
        - 'if [[ -z "\$UPSTREAM_REAL_IP_ADDRESS" ]]; then'
        - '  echo "UPSTREAM_REAL_IP_ADDRESS defaulting to 127.0.0.1"'
        - '  export UPSTREAM_REAL_IP_ADDRESS=127.0.0.1'
        - 'fi'
        - ''
        - 'if [[ -z "\$UPSTREAM_REAL_IP_HEADER" ]]; then'
        - '  echo "UPSTREAM_REAL_IP_HEADER defaulting to X-Forwarded-For"'
        - '  export UPSTREAM_REAL_IP_HEADER=X-Forwarded-For'
        - 'fi'
        - ''
        - 'if [[ -z "\$UPSTREAM_REAL_IP_RECURSIVE" ]]; then'
        - '  echo "UPSTREAM_REAL_IP_RECURSIVE defaulting to off"'
        - '  export UPSTREAM_REAL_IP_RECURSIVE=off'
        - 'fi'
        - ''
        - 'if [[ -z "\$FRAPPE_SITE_NAME_HEADER" ]]; then'
        - '  # shellcheck disable=SC2016'
        - '  echo "FRAPPE_SITE_NAME_HEADER defaulting to \$host"'
        - '  # shellcheck disable=SC2016'
        - '  export FRAPPE_SITE_NAME_HEADER=\$host"
        - 'fi'
        - ''
        - 'if [[ -z "\$PROXY_READ_TIMEOUT" ]]; then'
        - '  echo "PROXY_READ_TIMEOUT defaulting to 120"'
        - '  export PROXY_READ_TIMEOUT=120'
        - 'fi'
        - 'if [[ -z "\$CLIENT_MAX_BODY_SIZE" ]]; then'
        - '  echo "CLIENT_MAX_BODY_SIZE defaulting to 50m"'
        - '  export CLIENT_MAX_BODY_SIZE=50m'
        - 'fi'
        - ''
        - '# shellcheck disable=SC2016'
        - 'envsubst ''\${BACKEND} \${SOCKETIO} \${UPSTREAM_REAL_IP_ADDRESS} \${UPSTREAM_REAL_IP_HEADER} \${UPSTREAM_REAL_IP_RECURSIVE} \${FRAPPE_SITE_NAME_HEADER} \${PROXY_READ_TIMEOUT} \${CLIENT_MAX_BODY_SIZE}'' </templates/nginx/frappe.conf.template >/etc/nginx/conf.d/frappe.conf
        - 'nginx -g ''daemon off;'' '
        - EOF
        - '# Make the script executable'
        - RUN chmod a+x startup.sh
        - 'CMD ["startup.sh"]'
    depends_on:
      - $$cap_appname-backend
      - $$cap_appname-websocket
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    environment:
      BACKEND: srv-captain--$$cap_appname-backend:$$cap_BACKEND_PORT
      SOCKETIO: srv-captain--$$cap_appname-websocket:$$cap_SOCKETIO_PORT
      FRAPPE_SITE_NAME_HEADER: $$cap_appname.$$cap_root_domain
      UPSTREAM_REAL_IP_ADDRESS: $$cap_UPSTREAM_REAL_IP_ADDRESS
      UPSTREAM_IP_HEADER: $$cap_UPSTREAM_REAL_IP_HEADER
      UPSTREAM_IP_RECURSIVE: $$cap_UPSTREAM_IP_RECURSIVE
      PROXY_READ_TIMEOUT: $$cap_PROXY_READ_TIMEOUT
      CLIENT_MAX_BODY_SIZE: $$cap_CLIENT_MAX_BODY_SIZE
  $$cap_appname-websocket:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["node", "/home/frappe/frappe-bench/apps/frappe/socketio.js"]
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    environment:
      FRAPPE_SITE: $$cap_appname.$$cap_root_domain
      FRAPPE_REDIS_CACHE: redis://srv-captain--$$cap_appname-redis-cache:6379
      FRAPPE_REDIS_QUEUE: redis://srv-captain--$$cap_appname-redis-queue:6379
      FRAPPE_SOCKETIO_PORT: $$cap_SOCKETIO_PORT
    platform: linux/amd64
  $$cap_appname-queue-short:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["bench", "worker", "--queue", "short,default"]
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
  $$cap_appname-queue-long:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["bench", "worker", "--queue", "long,default,short"]
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
  $$cap_appname-scheduler:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION
        - CMD ["bench", "scheduler"]
    platform: linux/amd64
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
  $$cap_appname-site-creator:
    caproverExtra:
      notExposeAsWebApp: true
      dockerfileLines:
        - 'FROM frappe/$$cap_APP_TYPE:$$cap_APP_VERSION'
        - '# Create a multi-line startup.sh script during image build'
        - 'RUN echo ''#/bin/bash'' > startup.sh && cat >> startup.sh <<''EOF'''
        - 'wait-for-it -t 120 \$DB_HOST:\$DB_PORT;'
        - 'wait-for-it -t 120 \$REDIS_CACHE;'
        - 'wait-for-it -t 120 \$REDIS_SOCKETIO;'
        - 'wait-for-it -t 120 \$REDIS_QUEUE;'
        - 'echo "\$(ls -1 sites)";'
        - '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";'
        - 'if [ ! -d "sites/\$SITE" ]; then'
        - '  echo "Ready to create \$SITE";'
        - '  bench new-site --no-mariadb-socket --db-root-username=\$DB_ROOT_USER --db-root-password=\$DB_ROOT_PASSWORD --admin-password=\$ADMINISTRATOR_PASSWORD --install-app erpnext --set-default \$SITE --force;'
        - '  bench add-system-manager --email=\$USER_EMAIL --password=\$USER_PASSWORD;'
        - '  bench scheduler enable;'
        - 'fi;'
        - ''
        - 'echo "New site $SITE created sucessfully!";'
        - EOF
        - '# Make the script executable'
        - RUN chmod a+x startup.sh
        - 'CMD ["startup.sh"]'
    platform: linux/amd64
    depends_on:
      configurator:
        condition: service_completed_successfully
    volumes:
      - $$cap_appname-sites:/home/frappe/frappe-bench/sites
      - $$cap_appname-logs:/home/frappe/frappe-bench/logs
    environment:
      #DB_HOST: srv-captain--$$cap_appname-db
      #DB_PORT: "3306"
      DB_HOST: $$cap_DB_HOST
      DB_PORT: $$cap_DB_PORT
      DB_ROOT_USER: $$cap_DB_ROOT_USER
      DB_ROOT_PASSWORD: $$cap_DB_ROOT_PASSWORD
      REDIS_CACHE: srv-captain--$$cap_appname-redis-cache:6379
      REDIS_QUEUE: srv-captain--$$cap_appname-redis-queue:6379
      REDIS_SOCKETIO: srv-captain--$$cap_appname-redis-queue:6379
      ADMINISTRATOR_PASSWORD: $$cap_ADMINISTRATOR_PASSWORD
      SITE: $$cap_appname.$$cap_root_domain
      USER_EMAIL: $$cap_USER_EMAIL
      USER_PASSWORD: $$cap_USER_PASSWORD
volumes:
  $$cap_appname-db-data: null
  $$cap_appname-sites: null
  $$cap_appname-logs: null
  $$cap_appname-redis-queue-data: null
  $$cap_appname-redis-cache-data: null