Install ERPNext V13 on a Synology NAS [DS 920+] using Docker

Hello @revant_one and everyone,
Following is my Docker-compose.yml file which is used to install ERPnext latest version(V14-dev) on docker. But i wanted to install v13.51.0 production version, how can i update following file so i will able to install v13 on docker

version: "3.9"
services:
  redis-queue:
    image: redis
    container_name: ERPNext-REDIS-QUEUE
    hostname: redis-queue
    mem_limit: 256m
    mem_reservation: 50m
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    read_only: true
    user: 1026:100
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping || exit 1"]
    volumes:
      - /volume1/docker/erpnext/redis-queue:/data:rw
      - /etc/localtime:/etc/localtime:ro
    restart: on-failure:5

  redis-cache:
    image: redis
    container_name: ERPNext-REDIS-CACHE
    hostname: redis-cache
    mem_limit: 256m
    mem_reservation: 50m
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    read_only: true
    user: 1026:100
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping || exit 1"]
    volumes:
      - /volume1/docker/erpnext/redis-cache:/data:rw
      - /etc/localtime:/etc/localtime:ro
    restart: on-failure:5

  redis-socketio:
    image: redis
    container_name: ERPNext-REDIS-SOCKETIO
    hostname: redis-socketio
    mem_limit: 256m
    mem_reservation: 50m
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    read_only: true
    user: 1026:100
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping || exit 1"]
    volumes:
      - /volume1/docker/erpnext/redis-socketio:/data:rw
      - /etc/localtime:/etc/localtime:ro
    restart: on-failure:5

  db:
    image: mariadb:10.8-jammy
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --skip-character-set-client-handshake
    container_name: ERPNext-DB
    hostname: erpnext-db
    mem_limit: 1g
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    user: 1026:100
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -u root -prootpass | grep 'mysqld is alive' || exit 1"]
    volumes:
      - /volume1/docker/erpnext/db:/var/lib/mysql:rw
      - /etc/localtime:/etc/localtime:ro
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
    restart: on-failure:5

  configurator:
    image: frappe/erpnext:latest
    entrypoint:
      - bash
      - -c
    command:
      - >
        ls -1 apps > sites/apps.txt;
        bench set-config -g db_host erpnext-db;
        bench set-config -gp db_port 3306;
        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 9000;
    container_name: ERPNext-CONFIGURATOR
    hostname: configurator
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/erpnext/sites:/home/frappe/frappe-bench/sites:rw
      - /volume1/docker/erpnext/logs:/home/frappe/frappe-bench/logs:rw
      - /etc/localtime:/etc/localtime:ro
    environment:
      DB_HOST: erpnext-db
      DB_PORT: 3306
      REDIS_CACHE: redis-cache
      REDIS_QUEUE: redis-queue
      REDIS_SOCKETIO: redis-socketio
      SOCKETIO_PORT: 9000
    restart: "no"
    depends_on:
      redis-queue:
        condition: service_healthy
      redis-cache:
        condition: service_healthy
      redis-socketio:
        condition: service_healthy
      db:
        condition: service_healthy

  backend:
    image: frappe/erpnext:latest
    container_name: ERPNext-BACKEND
    hostname: backend
    mem_limit: 1g
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/erpnext/sites:/home/frappe/frappe-bench/sites:rw
      - /volume1/docker/erpnext/logs:/home/frappe/frappe-bench/logs:rw
      - /etc/localtime:/etc/localtime:ro
    restart: on-failure:5
    depends_on:
      configurator:
        condition: service_completed_successfully

  websocket:
    image: frappe/erpnext:latest
    command:
      - node
      - /home/frappe/frappe-bench/apps/frappe/socketio.js
    container_name: ERPNext-WEBOSCKET
    hostname: websocket
    mem_limit: 1g
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/erpnext/sites:/home/frappe/frappe-bench/sites:rw
      - /volume1/docker/erpnext/logs:/home/frappe/frappe-bench/logs:rw
      - /etc/localtime:/etc/localtime:ro
    restart: on-failure:5
    depends_on:
      configurator:
        condition: service_completed_successfully

  create-site:
    image: frappe/erpnext:latest
    entrypoint:
      - bash
      - -c
    command:
      - >
        wait-for-it -t 120 erpnext-db:3306;
        wait-for-it -t 120 redis-cache:6379;
        wait-for-it -t 120 redis-queue:6379;
        wait-for-it -t 120 redis-socketio: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";
        bench new-site Frappe --no-mariadb-socket --mariadb-root-password=rootpass --admin-password=admin --install-app=erpnext --set-default;
    container_name: ERPNext-CREATE-SITE
    hostname: create-site
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/erpnext/sites:/home/frappe/frappe-bench/sites:rw
      - /volume1/docker/erpnext/logs:/home/frappe/frappe-bench/logs:rw
      - /etc/localtime:/etc/localtime:ro
    restart: "no"
    depends_on:
      configurator:
        condition: service_completed_successfully

  queue-default:
    image: frappe/erpnext:latest
    command: bench worker --queue default
    container_name: ERPNext-QUEUE-DEFAULT
    hostname: queue-default
    mem_limit: 1g
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/erpnext/sites:/home/frappe/frappe-bench/sites:rw
      - /volume1/docker/erpnext/logs:/home/frappe/frappe-bench/logs:rw
      - /etc/localtime:/etc/localtime:ro
    restart: on-failure:5
    depends_on:
      configurator:
        condition: service_completed_successfully
 
  queue-long:
    image: frappe/erpnext:latest
    command: bench worker --queue long
    container_name: ERPNext-QUEUE-LONG
    hostname: queue-long
    mem_limit: 1g
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/erpnext/sites:/home/frappe/frappe-bench/sites:rw
      - /volume1/docker/erpnext/logs:/home/frappe/frappe-bench/logs:rw
      - /etc/localtime:/etc/localtime:ro
    restart: on-failure:5
    depends_on:
      configurator:
        condition: service_completed_successfully
 
  queue-short:
    image: frappe/erpnext:latest
    command: bench worker --queue short
    container_name: ERPNext-QUEUE-SHORT
    hostname: queue-short
    mem_limit: 1g
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/erpnext/sites:/home/frappe/frappe-bench/sites:rw
      - /volume1/docker/erpnext/logs:/home/frappe/frappe-bench/logs:rw
      - /etc/localtime:/etc/localtime:ro
    restart: on-failure:5
    depends_on:
      configurator:
        condition: service_completed_successfully
 
  scheduler:
    image: frappe/erpnext:latest
    command: bench schedule
    container_name: ERPNext-SCHEDULER
    hostname: scheduler
    mem_limit: 1g
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/erpnext/sites:/home/frappe/frappe-bench/sites:rw
      - /volume1/docker/erpnext/logs:/home/frappe/frappe-bench/logs:rw
      - /etc/localtime:/etc/localtime:ro
    restart: on-failure:5
    depends_on:
      configurator:
        condition: service_completed_successfully

  frontend:
    image: frappe/erpnext:latest
    command:
      - nginx-entrypoint.sh
    container_name: ERPNext-FRONTEND
    hostname: frontend
    mem_limit: 1g
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    ports:
      - 8345:8080
    volumes:
      - /volume1/docker/erpnext/sites:/home/frappe/frappe-bench/sites:rw
      - /volume1/docker/erpnext/logs:/home/frappe/frappe-bench/logs:rw
      - /etc/localtime:/etc/localtime:ro
    environment:
      BACKEND: backend:8000
      FRAPPE_SITE_NAME_HEADER: Frappe
      SOCKETIO: websocket:9000
      UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
      UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
      UPSTREAM_REAL_IP_RECURSIVE: "off"
      PROXY_READ_TIMOUT: 120
      CLIENT_MAX_BODY_SIZE: 50m
    restart: on-failure:5
    depends_on:
      backend:
        condition: service_started
      websocket:
        condition: service_started

Use exact tag for version 13 here and everywhere else in image. E.g. image: frappe/erpnext:v13.51.6

Yes, I try to replace version with latest but following error shown

GET http://ip:8345/erpnext-web.bundle.css?ver=sg1K1IRU net::ERR_ABORTED 404 (NOT FOUND)
:8345/erpnext-web.bundle.js?ver=sg1K1IRU:1 GET http://ip:8345/erpnext-web.bundle.js?ver=sg1K1IRU net::ERR_ABORTED 404 (NOT FOUND)
DevTools failed to load source map: Could not load content for http://ip:8345/assets/js/socket.io.slim.js.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE
(index):36 GET http://ip:8345/erpnext-web.bundle.css?ver=xVbWpduU net::ERR_ABORTED 404 (NOT FOUND)
(index):36 GET http://ip:8345/erpnext-web.bundle.js?ver=xVbWpduU net::ERR_ABORTED 404 (NOT FOUND)
10The resource was preloaded using link preload but not used within a few seconds from the window’s load event. Please make sure it has an appropriate as value and it is preloaded intentionally.
jquery.min.js:4 POST http://ip:8345/ 500 (INTERNAL SERVER ERROR)
send @ jquery.min.js:4
ajax @ jquery.min.js:4
call @ website.js:79
login.call @ (index):1141
(anonymous) @ (index):1041
dispatch @ jquery.min.js:3
r.handle @ jquery.min.js:3
website.js:175 Traceback (most recent call last):
File “apps/frappe/frappe/app.py”, line 55, in application
init_request(request)
File “apps/frappe/frappe/app.py”, line 141, in init_request
frappe.local.http_request = frappe.auth.HTTPRequest()
File “apps/frappe/frappe/auth.py”, line 36, in init
self.set_session()
File “apps/frappe/frappe/auth.py”, line 70, in set_session
frappe.local.login_manager = LoginManager()
File “apps/frappe/frappe/auth.py”, line 117, in init
if self.login() == False:
File “apps/frappe/frappe/auth.py”, line 154, in login
self.post_login()
File “apps/frappe/frappe/auth.py”, line 161, in post_login
self.make_session()
File “apps/frappe/frappe/auth.py”, line 212, in make_session
frappe.local.session_obj = Session(
File “apps/frappe/frappe/sessions.py”, line 219, in init
self.start()
File “apps/frappe/frappe/sessions.py”, line 249, in start
self.insert_session_record()
File “apps/frappe/frappe/sessions.py”, line 267, in insert_session_record
frappe.db.sql(
File “apps/frappe/frappe/database/database.py”, line 187, in sql
self._cursor.execute(query, values)
File “env/lib/python3.9/site-packages/pymysql/cursors.py”, line 148, in execute
result = self._query(query)
File “env/lib/python3.9/site-packages/pymysql/cursors.py”, line 310, in _query
conn.query(q)
File “env/lib/python3.9/site-packages/pymysql/connections.py”, line 548, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File “env/lib/python3.9/site-packages/pymysql/connections.py”, line 775, in _read_query_result
result.read()
File “env/lib/python3.9/site-packages/pymysql/connections.py”, line 1156, in read
first_packet = self.connection._read_packet()
File “env/lib/python3.9/site-packages/pymysql/connections.py”, line 725, in _read_packet
packet.raise_for_error()
File “env/lib/python3.9/site-packages/pymysql/protocol.py”, line 221, in raise_for_error
err.raise_mysql_exception(self._data)
File “env/lib/python3.9/site-packages/pymysql/err.py”, line 143, in raise_mysql_exception
raise errorclass(errno, errval)
pymysql.err.OperationalError: (1054, “Unknown column ‘device’ in ‘field list’”)

You’ve to clean up your previous setup and related volumes and start fresh. You cannot install previous version of frappe/erpnext on existing newer version of frappe/erpnext.

Hello @revant_one
I use NAS DS923+ and like Shraddha33 I also use Docker-compose to install v15. However, when deploying I get an error but then the system still creates the image and the necessary voulume. But when connecting to the site I get the Internal Server Error message. I check the backend and it shows the following message:
“File “/home/frappe/frappe-bench/apps/frappe/frappe/model/meta.py”, line 124, in load_from_db
super().load_from_db()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 201, in load_from_db
self.set(df.fieldname, children)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 245, in set
self.extend(key, value)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 312, in extend
self.append(key, v)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 271, in append
d = self._init_child(value, key)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 330, in init_child
value = get_controller(doctype)(value)
^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 71, in get_controller
site_controllers[doctype] = import_controller(doctype)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 91, in import_controller
module = load_doctype_module(doctype, module_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/modules/utils.py”, line 247, in load_doctype_module
app = get_module_app(module)
^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/modules/utils.py”, line 272, in get_module_app
frappe.throw(
(“Module {} not found”).format(module), exc=frappe.DoesNotExistError)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 691, in throw
msgprint(
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 652, in msgprint
_raise_exception()
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 603, in raise_exception
raise exc
frappe.exceptions.DoesNotExistError: Module Core not found
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “/home/frappe/frappe-bench/env/lib/python3.11/site-packages/gunicorn/workers/gthread.py”, line 282, in handle
keepalive = self.handle_request(req, conn)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/env/lib/python3.11/site-packages/gunicorn/workers/gthread.py”, line 334, in handle_request
respiter = self.wsgi(environ, resp.start_response)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/app.py”, line 80, in application
app(environ, start_response),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/env/lib/python3.11/site-packages/werkzeug/wrappers/request.py”, line 190, in application
resp = f(*args[:-2] + (request,))
^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/app.py”, line 133, in application
response = handle_exception(e)
^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/app.py”, line 419, in handle_exception
response = get_response(“message”, http_status_code=http_status_code)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/serve.py”, line 28, in get_response
response = ErrorPage(exception=e).render()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py”, line 84, in render
html = self.get_html()
^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/utils.py”, line 528, in cache_html_decorator
html = func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py”, line 92, in get_html
self.init_context()
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/error_page.py”, line 14, in init_context
super().init_context()
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/base_template_page.py”, line 15, in init_context
self.context.update(get_website_settings())
^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/website/doctype/website_settings/website_settings.py”, line 174, in get_website_settings
settings: “WebsiteSettings” = frappe.get_cached_doc(“Website Settings”)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 1261, in get_cached_doc
doc = get_doc(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 1387, in get_doc
doc = frappe.model.document.get_doc(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 85, in get_doc
controller = get_controller(doctype)
^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 71, in get_controller
site_controllers[doctype] = import_controller(doctype)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 91, in import_controller
module = load_doctype_module(doctype, module_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/modules/utils.py”, line 247, in load_doctype_module
app = get_module_app(module)
^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/modules/utils.py”, line 272, in get_module_app
frappe.throw(
(“Module {} not found”).format(module), exc=frappe.DoesNotExistError)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 691, in throw
msgprint(
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 652, in msgprint
_raise_exception()
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 603, in _raise_exception
raise exc
frappe.exceptions.DoesNotExistError: Module Website not found”

The yml I use is similar to Shraddha33. Do you have any way to help me solve this problem?

hi @bopham , Please share me your common_site_config.json file