Installing ERPNext on a server using a Portainer stack behind Nginx Proxy Manager

I am looking to installing ERPNext on a server using a Portainer stack behind Nginx Proxy Manager (NPM).
Does anyone have experience with that?

in addition, i would like to be sure to be able to install custom apps later on.

Google search for Portainer and npm

more: frappe_docker/single-compose-setup.md at main · frappe/frappe_docker · GitHub

custom apps: Container Builds - #2 by revant_one

thx @revant_one ,
i already have successfully installed portainer and npm on my server and now looking forward to installing ERPNext from within portainer.
e.g. properly configure a portainer stack to do so.
Do you or know someone know how to do that?

btw, i’m looking to do so for 2 different sites. one for a company of a friend and one for a non-profit.

Using this to generate the docker compose file needed for my site (behind Portainer and NPM), i managed to make it work.
below is the extract of my custom docker-compose which i use in the portainer stack along with the .env for easier deployment:

version: "3"
services:
  backend:
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/erpnext:${ERPNEXT_VERSION}
    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:
      erpnextdb:
        condition: service_healthy
      redis-cache:
        condition: service_started
      redis-queue:
        condition: service_started
      redis-socketio:
        condition: service_started
    entrypoint:
    - bash
    - -c
    environment:
      DB_HOST: erpnextdb
      DB_PORT: "3306"
      REDIS_CACHE: redis-cache:6379
      REDIS_QUEUE: redis-queue:6379
      REDIS_SOCKETIO: redis-socketio:6379
      SOCKETIO_PORT: "19000"
      DB_ROOT_USER: ${DB_ROOT_USER}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    image: frappe/erpnext:${ERPNEXT_VERSION}
    networks:
      default: null
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
  erpnextdb:
    command:
    - --character-set-server=utf8mb4
    - --collation-server=utf8mb4_unicode_ci
    - --skip-character-set-client-handshake
    - --skip-innodb-read-only-compressed
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    healthcheck:
      test:
      - CMD-SHELL
      - mysqladmin ping -h localhost --password=${MYSQL_ROOT_PASSWORD}
      interval: 1s
      retries: 15
    image: mariadb:10.6
    networks:
      default: null
    volumes:
    - type: volume
      source: db-data
      target: /var/lib/mysql
      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: ${SITE_NAME}
      PROXY_READ_TIMOUT: "120"
      SOCKETIO: websocket:19000
      UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
      UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
      UPSTREAM_REAL_IP_RECURSIVE: "off"
    image: frappe/erpnext:${ERPNEXT_VERSION}
    networks:
      default: null
    ports:
    - mode: ingress
      target: 8080
      published: "18080"
      protocol: tcp
    volumes:
    - type: volume
      source: sites
      target: /home/frappe/frappe-bench/sites
      volume: {}
  queue-default:
    command:
    - bench
    - worker
    - --queue
    - default
    depends_on:
      configurator:
        condition: service_completed_successfully
    image: frappe/erpnext:${ERPNEXT_VERSION}
    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:${ERPNEXT_VERSION}
    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:${ERPNEXT_VERSION}
    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:${ERPNEXT_VERSION}
    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:${ERPNEXT_VERSION}
    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:${ERPNEXT_VERSION}
  volumes:
  - sites:/home/frappe/frappe-bench/sites
x-customizable-image:
  image: frappe/erpnext:${ERPNEXT_VERSION}
x-depends-on-configurator:
  depends_on:
    configurator:
      condition: service_completed_successfully

.env file:

ERPNEXT_VERSION=v14
DB_ROOT_USER=root
MYSQL_ROOT_PASSWORD=CHANGEMEf7t3c48wfbvh56e
SITE_NAME=changeme.example.org

once the stack is on, i need to create the site from within the console of the backend:

bench new-site changeme.example.org

and then

bench use changeme.example.org
bench enable-scheduler

then i installed the erpnext app:

bench --site changeme.example.org install-app erpnext

then i configured NPM to point to port 18080 and everything worked fine, i was able to use frappe and erpnext.

then i needed to have my own application where i use custom modules and create custom forms and doctypes, but my site stops as soon as i create it and install it:

bench new-app app-name
bench --site changeme.example.org install-app

i think i am missing some steps between the new-app command and install-app command where maybe i need to create some configuration to the app…

can anyone support in how to do this last step?

the error i’m receiving is

Couldn't find supervisorctl in PATH

after manually installing supervisor using:

pip install sypervisor

i do bench restart and get this error:

frappe@80db489af380:~/frappe-bench$ bench restart
$ supervisorctl restart frappe:
error: <class 'OSError'>, [Errno 99] Cannot assign requested address: file: /usr/local/lib/python3.10/socket.py line: 833
ERROR: 
Traceback (most recent call last):
  File "/usr/local/bin/bench", line 8, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.10/site-packages/bench/cli.py", line 127, in cli
    bench_command()
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/bench/commands/utils.py", line 41, in restart
    Bench(".").reload(web, supervisor, systemd)
  File "/usr/local/lib/python3.10/site-packages/bench/utils/render.py", line 126, in wrapper_fn
    return fn(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/bench/bench.py", line 151, in reload
    restart_supervisor_processes(bench_path=self.name, web_workers=web, _raise=_raise)
  File "/usr/local/lib/python3.10/site-packages/bench/utils/bench.py", line 315, in restart_supervisor_processes
    failure = bench.run(f"{sudo}supervisorctl restart {group}", _raise=_raise)
  File "/usr/local/lib/python3.10/site-packages/bench/bench.py", line 48, in run
    return exec_cmd(cmd, cwd=cwd or self.cwd, _raise=_raise)
  File "/usr/local/lib/python3.10/site-packages/bench/utils/__init__.py", line 158, in exec_cmd
    raise CommandFailedError
bench.exceptions.CommandFailedError

please advise

creating a new app using:

bench new-app myapp

generates the below log:

'myapp' created at /home/frappe/frappe-bench/apps/myapp
Installing myapp
$ /home/frappe/frappe-bench/env/bin/python -m pip install --quiet --upgrade -e /home/frappe/frappe-bench/apps/myapp 
$ bench build --app myapp
✔ Application Assets Linked                                                                 

yarn run v1.22.19
$ node esbuild --production --apps myapp --run-build-command
File                                                        Size

 DONE  Total Build Time: 1.196s

clean: postcss.plugin was deprecated. Migration guide:
https://evilmartians.com/chronicles/postcss-8-plugin-migration
Done in 2.29s.
WARN: restart failed: Couldn't find supervisorctl in PATH

Containers are immutable.
you’ll need to build custom image for apps.

search forum for more. go through posts related to container basics and container builds

supervisor is not required in containers. container orchestration does the job of supervisor.

also new-site needs --no-mariadb-socket when used in containers