Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung IT-Branche 19.07.2026 · 12 min Lesezeit

ERPNext mit Docker installieren: Vollständiges Open-Source-ERP für KMU

ERPNext ist mit 35.000+ GitHub-Stars das umfassendste kostenlose ERP-System der Welt. Diese Anleitung zeigt dir, wie du Buchhaltung, Lager, HR, CRM und Fertigung per Docker Compose auf einem beliebigen Linux-Server startest – ohne SAP-Lizenzkosten.

ERPNext mit Docker installieren: Open Source ERP für KMU mit Linux Server, Docker Container, zentraler Datenbank und Dashboard für Finanzen, Lager, Kunden und Projekte.

Wer als KMU ein vollständiges ERP-System sucht, stolpert schnell über fünfstellige Lizenzkosten für SAP Business One oder Microsoft Dynamics. ERPNext bietet denselben Funktionsumfang – doppelte Buchführung, Lager, Einkauf und Verkauf, Fertigung, HRMS, CRM, Projektmanagement und POS – als GPL-3.0-lizenzierte Open-Source-Software ohne jegliche Lizenzgebühren. Mit dem offiziellen frappe/frappe_docker-Repository läuft ERPNext auf jedem Linux-Host via Docker Compose, egal ob dedizierter Server, Cloud-VPS oder NAS. Diese Anleitung führt dich durch die komplette Installation auf Basis von ERPNext v16 mit allen neun Microservices, erklärt die Besonderheiten der Frappe-Architektur und zeigt typische Fallstricke, die beim ersten Start beinahe jeden treffen.

Voraussetzungen

  1. Docker Engine v24.0+ und Docker Compose Plugin v2 installiert – docker compose mit Leerzeichen (nicht docker-compose). Wer die Basis noch einrichten muss, findet eine vollständige Schritt-für-Schritt-Anleitung unter Docker und Docker Compose auf Linux installieren.
  2. Linux-Host (Ubuntu 22.04/24.04 empfohlen), macOS oder Windows mit Docker Desktop. ARM64 wird offiziell unterstützt.
  3. Mindestens 4 GB RAM für Tests und Evaluierung; 8 GB RAM und 4 CPU-Kerne für den Produktivbetrieb. Mit weniger als 4 GB RAM stürzen Queue-Worker oder Gunicorn ab (Out-of-Memory, Symptom: 502/504).
  4. Mindestens 40 GB freier Speicherplatz (Image-Download ca. 2–3 GB, Produktionsempfehlung 160 GB SSD).
  5. Optionale, aber empfohlene Domain mit DNS für HTTPS – ein vorgelagerter Reverse-Proxy (Traefik oder Nginx Proxy Manager) übernimmt TLS-Terminierung.

Schritt 1: Eckdaten und Architektur verstehen

ERPNext v16 setzt auf eine Microservice-Architektur mit neun Containern. Bevor du startest, lohnt ein Blick auf die Kerngrößen:

EigenschaftWert
Image (ERPNext)frappe/erpnext:v16.22.0 (Docker Hub) / ghcr.io/frappe/erpnext:v16.22.0 (GHCR)
Image (Datenbank)mariadb:11.8
Image (Cache/Queue)redis:6.2-alpine (zwei Instanzen)
Öffentlicher Port8080 → Nginx-Frontend
Interne Portsbackend:8000, websocket:9000, db:3306, redis:6379 – alle nur containerseitig
LizenzGPL-3.0, kostenlos, kein Vendor-Lock-in
Architekturx86_64 und ARM64 (Multi-Arch-Images)
VolumeZweckKritisch?
sitesFrappe-Bench-Konfiguration, Site-Daten, UploadsJa – Datenverlust bei Löschung
db-dataMariaDB-DatenbankdateienJa – Datenverlust bei Löschung
redis-queue-dataPersistente Job-Queue für HintergrundaufgabenEmpfohlen
logsAnwendungslogsOptional

Die Container configurator und create-site sind Init-Container – sie laufen einmalig durch und beenden sich dann (Exitcode 0). Das ist kein Fehler, sondern das korrekte Verhalten. Alle anderen sieben Container laufen dauerhaft.

Verifizieren: Prüfe Docker und Compose-Version mit docker --version und docker compose version. Du solltest mindestens Docker version 24.x und Docker Compose version v2.x sehen. Weniger als 4 GB freien RAM? Dann zuerst Ressourcen prüfen: free -h.

Schritt 2: Projektordner anlegen

Lege einen dedizierten Ordner für den ERPNext-Stack an. Alle Konfigurationsdateien kommen hier rein:

mkdir -p /opt/erpnext
cd /opt/erpnext

Du kannst stattdessen auch ~/erpnext verwenden – wichtig ist nur, dass alle nachfolgenden Dateien im selben Verzeichnis liegen, damit docker compose sie findet.

Verifizieren: ls -la /opt/erpnext zeigt ein leeres Verzeichnis. Kein Fehler = korrekt.

Schritt 3: .env-Datei mit sicheren Passwörtern anlegen

Die .env-Datei steuert alle geheimen und anpassbaren Werte. Lege sie vor dem ersten Start an – nachträgliches Ändern der Passwörter bei laufender Datenbank erfordert zusätzliche Schritte.

# /opt/erpnext/.env
# ERPNext Version – exaktes Image-Tag
ERPNEXT_VERSION=v16.22.0

# MariaDB Root-Passwort (NIEMALS den Default "123" oder "changeme" verwenden!)
DB_PASSWORD=sEhrSicheresDbPasswort42!

# ERPNext Admin-Passwort (für Login als "Administrator" im Browser)
ADMIN_PASSWORD=nochEinSicheresAdminPw!

# Öffentlicher HTTP-Port (Standard: 8080)
HTTP_PUBLISH_PORT=8080

# Optional: Gunicorn-Worker (Faustregel: 2 × CPU-Kerne + 1)
GUNICORN_WORKERS=2

# Optional: Nginx Upload-Limit und Timeout
CLIENT_MAX_BODY_SIZE=50m
PROXY_READ_TIMEOUT=120

Vergib unterschiedliche, starke Passwörter für DB_PASSWORD und ADMIN_PASSWORD. Ein einfaches Werkzeug für sichere Passwörter: openssl rand -base64 24. Die Datei gehört auf 600:

chmod 600 /opt/erpnext/.env

Verifizieren: cat /opt/erpnext/.env zeigt die Werte. Beide Passwörter sind unterschiedlich und enthalten Sonderzeichen. Dateiberechtigung: ls -la /opt/erpnext/.env-rw-------.

Schritt 4: compose.yaml anlegen

Die folgende compose.yaml basiert auf der offiziellen pwd.yml aus dem frappe/frappe_docker-Repository und ist für den Standalone-Betrieb auf einem einzelnen Host optimiert. YAML-Anker (&customizable_image, *backend_defaults) reduzieren Wiederholungen deutlich – das ist valides Docker-Compose-v2-Syntax:

# /opt/erpnext/compose.yaml
# ERPNext v16 – Docker Compose (Standalone, plattformneutral)
# Quelle: github.com/frappe/frappe_docker

x-customizable-image: &customizable_image
  image: frappe/erpnext:${ERPNEXT_VERSION:-v16.22.0}
  pull_policy: always

x-depends-on-configurator: &depends_on_configurator
  depends_on:
    configurator:
      condition: service_completed_successfully

x-backend-defaults: &backend_defaults
  <<: [*depends_on_configurator, *customizable_image]
  volumes:
    - sites:/home/frappe/frappe-bench/sites
    - logs:/home/frappe/frappe-bench/logs
  networks:
    - frappe_network

services:

  # ---------- Datenbank ----------
  db:
    image: mariadb:11.8
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 5s
      retries: 10
    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_PASSWORD:-changeme_now}
      MYSQL_DATABASE: frappe
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - frappe_network

  # ---------- Redis Cache (flüchtig) ----------
  redis-cache:
    image: redis:6.2-alpine
    restart: unless-stopped
    networks:
      - frappe_network

  # ---------- Redis Queue (persistent) ----------
  redis-queue:
    image: redis:6.2-alpine
    restart: unless-stopped
    volumes:
      - redis-queue-data:/data
    networks:
      - frappe_network

  # ---------- Konfiguration (einmaliger Init-Container) ----------
  configurator:
    <<: *customizable_image
    restart: "no"
    command: >
      bash -c "
        bench set-config -g db_host db &&
        bench set-config -gp db_port 3306 &&
        bench set-config -g redis_cache redis://redis-cache:6379 &&
        bench set-config -g redis_queue redis://redis-queue:6379 &&
        bench set-config -gp socketio_port 9000
      "
    environment:
      DB_HOST: db
      DB_PORT: "3306"
      REDIS_CACHE: redis-cache:6379
      REDIS_QUEUE: redis-queue:6379
      SOCKETIO_PORT: "9000"
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs
    depends_on:
      db:
        condition: service_healthy
    networks:
      - frappe_network

  # ---------- Site-Erstellung (einmaliger Init-Container) ----------
  create-site:
    <<: *customizable_image
    restart: "no"
    command: >
      bash -c "
        wait-for-it -t 120 db:3306 &&
        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 | python3 -c \"import sys, json; config = json.load(sys.stdin); print(config.get('db_host', '').strip())\") ]]; do
          echo 'Warte auf Konfiguration ...' &&
          sleep 5 &&
          if (( $(date +%s) - start > 120 )); then echo 'Timeout!' && exit 1; fi;
        done &&
        echo 'Konfiguration vorhanden, erstelle Site ...' &&
        bench new-site --mariadb-root-password ${DB_PASSWORD:-changeme_now} --admin-password ${ADMIN_PASSWORD:-changeme_admin} --no-mariadb-socket frontend &&
        bench --site frontend install-app erpnext
      "
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs
    depends_on:
      configurator:
        condition: service_completed_successfully
    networks:
      - frappe_network

  # ---------- Backend (Gunicorn) ----------
  backend:
    <<: *backend_defaults
    restart: unless-stopped

  # ---------- WebSocket ----------
  websocket:
    <<: [*depends_on_configurator, *customizable_image]
    restart: unless-stopped
    command: node /home/frappe/frappe-bench/apps/frappe/socketio.js
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs
    networks:
      - frappe_network

  # ---------- Queue-Worker (kurze Jobs) ----------
  queue-short:
    <<: *backend_defaults
    restart: unless-stopped
    command: bench worker --num-workers 2 --queue short,default

  # ---------- Queue-Worker (lange Jobs) ----------
  queue-long:
    <<: *backend_defaults
    restart: unless-stopped
    command: bench worker --num-workers 1 --queue long,default,short

  # ---------- Scheduler ----------
  scheduler:
    <<: *backend_defaults
    restart: unless-stopped
    command: bench schedule

  # ---------- Frontend (Nginx Reverse Proxy) ----------
  frontend:
    <<: *customizable_image
    restart: unless-stopped
    command: nginx-entrypoint.sh
    environment:
      BACKEND: backend:8000
      FRAPPE_SITE_NAME_HEADER: frontend
      SOCKETIO: websocket:9000
      UPSTREAM_REAL_IP_ADDRESS: ${UPSTREAM_REAL_IP_ADDRESS:-127.0.0.1}
      UPSTREAM_REAL_IP_HEADER: ${UPSTREAM_REAL_IP_HEADER:-X-Forwarded-For}
      UPSTREAM_REAL_IP_RECURSIVE: ${UPSTREAM_REAL_IP_RECURSIVE:-off}
      PROXY_READ_TIMEOUT: ${PROXY_READ_TIMEOUT:-120}
      CLIENT_MAX_BODY_SIZE: ${CLIENT_MAX_BODY_SIZE:-50m}
    volumes:
      - sites:/home/frappe/frappe-bench/sites
      - logs:/home/frappe/frappe-bench/logs
    ports:
      - "${HTTP_PUBLISH_PORT:-8080}:8080"
    depends_on:
      - websocket
    networks:
      - frappe_network

volumes:
  sites:
  logs:
  db-data:
  redis-queue-data:

networks:
  frappe_network:
    driver: bridge

Wichtig: Der Site-Name frontend (im bench new-site-Befehl) muss mit dem Wert von FRAPPE_SITE_NAME_HEADER im frontend-Container übereinstimmen. Weichen beide ab, erscheint später im Browser „Site frontend not found".

Verifizieren: YAML-Syntax prüfen mit docker compose config – die Ausgabe zeigt die aufgelöste Konfiguration ohne Fehlermeldung. Alle neun Services sollten aufgelistet sein.

Schritt 5: Stack starten und Initialisierung abwarten

Starte alle Container im Hintergrund:

cd /opt/erpnext
docker compose up -d

Docker lädt nun alle Images herunter (ca. 2–3 GB, je nach Verbindung 5–15 Minuten) und startet die Container. Anschließend läuft der create-site-Container durch und legt die MariaDB-Datenbank an sowie installiert ERPNext. Diesen Prozess auf keinen Fall abbrechen. Verfolge den Fortschritt live:

docker compose logs -f create-site

Typischer Abschluss nach 5–10 Minuten – du siehst Ausgaben wie:

create-site-1  | Installing frappe...
create-site-1  | Installing erpnext...
create-site-1  | ERPNext has been installed successfully.
create-site-1 exited with code 0

Erst wenn create-site mit Exitcode 0 beendet ist, ist die Installation vollständig.

Verifizieren: Alle dauerhaften Dienste müssen laufen:

docker compose ps

Erwartetes Ergebnis (gekürzt):

NAME                    STATUS
erpnext-db-1            Up (healthy)
erpnext-redis-cache-1   Up
erpnext-redis-queue-1   Up
erpnext-backend-1       Up
erpnext-websocket-1     Up
erpnext-queue-short-1   Up
erpnext-queue-long-1    Up
erpnext-scheduler-1     Up
erpnext-frontend-1      Up
erpnext-configurator-1  Exited (0)
erpnext-create-site-1   Exited (0)

Die zwei Init-Container mit Exited (0) sind korrekt – alles andere mit Up ist das Ziel. Zusätzlicher HTTP-Check:

curl -I http://localhost:8080

Erwartete Antwort: HTTP/1.1 200 OK oder 302 Found (Redirect auf Login-Seite).

Schritt 6: Ersteinrichtung im Browser

Öffne http://localhost:8080 (oder die Server-IP) im Browser. Der Login-Screen erscheint:

  1. Benutzername: Administrator
  2. Passwort: Wert aus ADMIN_PASSWORD in der .env

Nach dem ersten Login startet automatisch der Setup Wizard. Hier wählst du Land (Deutschland), Sprache, Zeitzone und Währung. Für DACH-Betrieb ist die Auswahl „Germany" wichtig, da ERPNext dann die passenden Steuerkonten (SKR03/SKR04), UStVA-relevante Konfigurationen und DATEV-Export-Optionen vorschlägt. Der Setup-Assistent aktiviert außerdem die benötigten Module – nimm dir 5–10 Minuten dafür.

Prüfe nach dem Wizard, ob ERPNext korrekt installiert ist:

docker compose exec backend bench --site frontend list-apps

Erwartete Ausgabe:

frappe
erpnext

Verifizieren: Das ERPNext-Dashboard ist sichtbar, Module wie „Buchhaltung", „Lager" und „Einkauf" erscheinen in der Navigation. Taucht erpnext bei list-apps nicht auf, installiere es nach: docker compose exec backend bench --site frontend install-app erpnext.

Schritt 7: Backups einrichten

Backups sind Pflicht, bevor der Stack produktiv geht. ERPNext speichert seine Daten in zwei kritischen Volumes: sites (Konfiguration, Uploads) und db-data (MariaDB). Ein einfacher manueller Backup-Befehl:

# Site-Backup inklusive Uploads (landet in sites/frontend/private/backups/)
docker compose exec backend bench --site frontend backup --with-files

# MariaDB-Dump direkt aus dem Container
docker compose exec db mysqldump -uroot -p"${DB_PASSWORD}" frappe > /opt/erpnext/backup_frappe_$(date +%Y%m%d).sql

Für regelmäßige automatisierte Backups – inklusive Offsite-Kopie auf S3 oder Hetzner Storage Box – empfiehlt sich die Kombination aus cron und Restic. Eine vollständige Backup-Strategie beschreibt die Anleitung MySQL & PostgreSQL Backup automatisieren.

Verifizieren: ls -lh sites/frontend/private/backups/ (im Container oder per docker compose exec backend ls /home/frappe/frappe-bench/sites/frontend/private/backups/) zeigt .sql.gz- und .tar-Dateien mit aktuellem Datum.

Schritt 8: Updates durchführen

ERPNext wird aktiv gepflegt (Stand Juni 2026: 1.755 Releases, 58.504 Commits). Updates erfolgen über die .env-Datei:

# 1. Backup erstellen (Pflicht vor jedem Update!)
docker compose exec backend bench --site frontend backup --with-files

# 2. Neue Version in .env setzen, z.B.:
#    ERPNEXT_VERSION=v16.23.0

# 3. Neue Images ziehen und Container neu starten
docker compose pull
docker compose up -d

# 4. Datenbankmigrationen ausführen
docker compose exec backend bench --site frontend migrate

Wichtig: Schritt 4 (bench migrate) darf nicht übersprungen werden – ohne Datenbankmigrationen können nach einem Update Fehlermeldungen oder inkonsistente Daten auftreten.

Verifizieren: docker compose ps zeigt alle Dienste als Up. docker compose logs backend --tail=20 zeigt keine Fehlermeldungen. Im Browser unter Einstellungen → Über ERPNext ist die neue Version sichtbar.

Troubleshooting / Typische Fehler

  1. „create-site hat nach 10 Minuten noch nicht beendet": Das ist normal bei langsamer CPU oder wenig RAM. Weiter warten und mit docker compose logs -f create-site beobachten. Erst bei expliziter Fehlermeldung (nicht bei Wartemeldungen) handeln. Abbrechenwenn Exited (1) erscheint; dann Logs lesen.
  2. „Site frontend not found" im Browser: Der Site-Name in bench new-site ... frontend stimmt nicht mit FRAPPE_SITE_NAME_HEADER: frontend überein. Beide Werte müssen identisch sein. Prüfen: docker compose exec frontend printenv FRAPPE_SITE_NAME_HEADER.
  3. „Access denied for user 'root'" beim Starten: Das in .env gesetzte DB_PASSWORD stimmt nicht mit dem tatsächlichen MariaDB-Passwort überein. Passiert, wenn das db-data-Volume bereits mit einem anderen Passwort initialisiert wurde. Lösung: Volume löschen (nur möglich wenn keine Daten verloren gehen dürfen) und neu starten: docker compose down -v && docker compose up -d.
  4. 502/504 Bad Gateway: Meistens Out-of-Memory bei weniger als 4 GB RAM. docker compose logs backend --tail=50 zeigt Worker failed to boot. Lösung: RAM erhöhen oder GUNICORN_WORKERS=1 in .env setzen und Container neu starten.
  5. MariaDB startet nicht / healthcheck schlägt fehl: Die fehlenden Startparameter --character-set-server=utf8mb4 und --collation-server=utf8mb4_unicode_ci verursachen Zeichensatz-Fehler. In der compose.yaml sind diese unter command: enthalten – nicht entfernen.
  6. Nach docker compose down -v sind alle Daten weg: Das Flag -v löscht alle benannten Volumes inklusive sites und db-data. Für normales Herunterfahren immer nur docker compose down (ohne -v) verwenden.
  7. Keine Echtzeit-Updates / WebSocket-Fehler hinter Reverse-Proxy: Traefik oder Nginx als vorgelagerter Proxy muss WebSocket-Upgrade-Header korrekt weiterleiten (Upgrade, Connection). Fehlt dies, funktionieren Live-Benachrichtigungen und Echtzeit-Updates nicht. Symptom: keine Live-Aktualisierungen im Browser.
  8. Custom Apps (z. B. HRMS) lassen sich nicht nachinstallieren: Container sind ephemer – bench get-app in einen laufenden Container funktioniert nicht dauerhaft. Zusätzliche Frappe-Apps müssen beim Image-Build via APPS_JSON_BASE64 und dem offiziellen Containerfile aus dem frappe_docker-Repo eingebunden werden.

Häufige Fragen

Kann ich ERPNext auf ARM64 betreiben (Raspberry Pi 5, Apple M-Chip)?

Ja. Alle offiziellen ERPNext-Images werden als Multi-Arch-Images bereitgestellt und unterstützen linux/amd64 sowie linux/arm64. Das offizielle frappe_docker-Repository enthält außerdem einen dedizierten ARM64-Guide mit spezifischen Hinweisen für ARM-Hosts.

Wie führe ich ein Backup durch?

Innerhalb des laufenden Stacks: docker compose exec backend bench --site frontend backup --with-files. Die Backup-Dateien landen im sites-Volume unter sites/frontend/private/backups/. Zusätzlich sollte das db-data-Volume regelmäßig per mysqldump oder Volume-Snapshot gesichert werden.

Wie aktualisiere ich auf eine neue ERPNext-Version?

In der .env-Datei ERPNEXT_VERSION auf die neue Version setzen, dann docker compose pull && docker compose up -d ausführen. Anschließend unbedingt docker compose exec backend bench --site frontend migrate aufrufen. Vorher immer ein Backup erstellen.

Unterstützt ERPNext deutsche Buchhaltungsanforderungen?

ERPNext hat eine (teilweise) deutsche Übersetzung und unterstützt DATEV-Export, UStVA-relevante Steuerkonten sowie SKR03/SKR04-Kontenrahmen. Im Setup-Wizard wähle „Germany" als Land. Vollständige GoBD-Konformität erfordert möglicherweise zusätzliche Konfiguration und sollte mit einem Steuerberater abgestimmt werden.

Kann ich mehrere Sites (Multi-Tenancy) betreiben?

Ja, aber das erfordert die Multi-Bench-Overrides aus dem frappe_docker-Repository (overrides/compose.multi-bench.yaml) und typischerweise einen vorgelagerten Traefik-Proxy. Der hier beschriebene Standalone-Ansatz unterstützt nur eine einzige Site.

Was ist der Unterschied zwischen Docker Hub und GHCR für ERPNext-Images?

Beide Registries (frappe/erpnext auf Docker Hub und ghcr.io/frappe/erpnext auf GitHub Container Registry) sind identisch und werden synchron gepflegt. Das aktuelle README des frappe_docker-Repos empfiehlt ghcr.io als bevorzugte Registry.

Fazit

ERPNext via Docker Compose ist eine ernstzunehmende SAP-Alternative für KMU: GPL-lizenziert, aktiv gepflegt, mit vollständiger Buchhaltung, Lager, CRM, HRMS und Fertigung auf einer Plattform. Die neun Container sind beim ersten Blick einschüchternd, folgen aber einer klaren Logik – zwei Init-Container für die Initialisierung, sieben dauerhafte Dienste für den Betrieb. Die kritischen Punkte sind sichere Passwörter vor dem ersten Start, Geduld beim create-site-Prozess und konsequente Backups bevor die ersten echten Daten eingetragen werden. Für den Produktionsbetrieb ist ein vorgelagerter Reverse-Proxy für HTTPS und mindestens 8 GB RAM unverzichtbar. Wer diese Punkte beachtet, bekommt ein vollständiges ERP-System ohne Vendor-Lock-in und ohne monatliche Lizenzkosten.

Weiterführende Anleitungen und Quellen

  1. Docker und Docker Compose auf Linux installieren – Grundlage für alle Docker-basierten Selbst-Hosting-Projekte
  2. Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten – für SSL-Terminierung vor ERPNext
  3. MySQL & PostgreSQL Backup automatisieren – für regelmäßige MariaDB-Sicherungen
  4. Docker Compose absichern: Secrets, Healthchecks, Non-Root – Härtung für den Produktivbetrieb

Offizielle Quellen: frappe/frappe_docker auf GitHub (Referenz-Repository), Frappe Docker Dokumentation und ERPNext Dokumentation.