- Shell 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .idea | ||
| docs | ||
| .env | ||
| .gitignore | ||
| AGENTS.md | ||
| apps.json | ||
| build.sh | ||
| CLAUDE.md | ||
| docker-compose.dev-apps.yml | ||
| docker-compose.override.yml | ||
| docker-compose.prod.yml | ||
| docker-compose.yml | ||
| LICENSE | ||
| Projekt.md | ||
| README.md | ||
Frappe CRM + ERPNext – WSC Standard Stack
Selbst gehostete Frappe-Bench (Branch version-16) mit ERPNext und Frappe CRM, als Basis für
LeadScraper-Google, ecommerce_integrations und die deutsche ERPNext-Lokalisierung von ALYF
(siehe Projekt.md). Enthält außerdem ner-service, einen eigenständigen spaCy-basierten
Mini-Dienst zur Inhaber-Erkennung im LeadScraper-Impressum-Scan (Details: docs/install.md,
Abschnitt 9c).
Hinweis:
.enventhält lokale Platzhalter-Passwörter (change-me-local). Vor einem Live-Deploy durch echte Werte ersetzen. Werte, die je in Git lagen, gelten als kompromittiert → rotieren.
1. Voraussetzungen
- Docker Engine v23+ mit BuildKit (Pflicht für
--secretbeim Image-Build) + Docker Compose v2 - Für den Live-Betrieb zusätzlich: externes Netz
traefik_proxy_network, zentrale Stacksdocker-autoheal-neustart,docker-ofelia-cronjobs,docker-docker-backup-backups - Lokal (Default): keine zusätzlichen Stacks nötig, direkter Port-Zugriff
- Die Volume-Ordner unter
./volumes/müssen vor dem ersten Start existieren (siehe Schritt 2)
2. Image bauen
mkdir -p volumes/{sites,db,redis-queue,backups}
./build.sh
build.sh baut das Image frappe-crm-erp:version-16 per Remote-Git-Build-Context aus dem
offiziellen frappe/frappe_docker-Repo (images/custom/Containerfile), mit apps.json als
BuildKit-Secret. Kein Vendoring von frappe_docker in dieses Repo nötig.
Aktuell in apps.json: erpnext (Branch version-16), crm (Branch main), die eigenen
Apps LeadScraper-Google (main) und ecommerce_integrations (shopware6-dach), sowie die
drei ALYF-Apps zur deutschen Lokalisierung erpnext_germany/eu_einvoice/
erpnext_pdf-on-submit (alle version-16) — Details und Begründung siehe Projekt.md.
Nicht in
apps.json:erpnext_druckformateist keine installierbare Frappe-App, sondern ein einmalig auszuführendes CLI-Tool (frappe-pf-init). Alsapps.json-Eintrag verursacht es einen Crash-Loop (ModuleNotFoundError, ungültiger Python-Package-Name mit Bindestrichen) — sieheProjekt.md, Abschnitt „Deutsche Lokalisierung (ALYF)".
Weitere eigene Apps aufnehmen: Eintrag in apps.json ergänzen (Git-URL + Branch), dann
./build.sh erneut ausführen — CACHE_BUST sorgt automatisch dafür, dass wirklich neu
geklont wird (siehe Abschnitt 6).
frappe/erpnextlaufen bewusst auf dem fest versionierten Branchversion-16stattdevelop— reproduzierbar und kompatibel zu den eigenen Apps, die ebenfalls auf v16 laufen.crmhat keine eigenenversion-*-Branches;maindeklariertfrappe>=15.0.0,<17.0.0und ist damit zu v16 kompatibel.
Dauert ca. 20–40 Minuten — siehe Abschnitt 6 ("Warum dauert der Build so lange?").
3. Stack starten
Wichtig:
docker composeimmer aus diesem Stack-Verzeichnis starten (${PWD}-Mounts).
Startbefehle-Referenz (alle Szenarien)
| Szenario | Befehl | Compose-Dateien |
|---|---|---|
| Lokal, Standard (Default — kein Dev-Mount, direkter Port) | docker compose up -d |
docker-compose.yml + docker-compose.override.yml (automatisch, da kein -f angegeben) |
| Lokal, mit LeadScraper-Dev-Mount (Codeänderungen an der App sofort sichtbar, kein Rebuild — siehe Abschnitt 7) | docker compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.dev-apps.yml up -d |
Alle drei explizit — siehe Warnung unten |
| Live/Produktiv (Traefik statt Port, Autoheal/Backup-Labels aktiv) | docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d |
docker-compose.yml + docker-compose.prod.yml |
Achtung —
docker-compose.override.ymlwird nur automatisch geladen, wenndocker compose upkomplett OHNE-f-Flag aufgerufen wird (erste Zeile der Tabelle). Sobald irgendein-fexplizit angegeben wird (Dev-Mount- oder Live-Zeile), ersetzt das Docker Composes automatische Dateiauswahl vollständig —override.ymlmuss dann selbst mit aufgeführt werden, sonst fehlt der lokale Port-Zugriff ersatzlos (Symptom: Start läuft fehlerfrei durch, abercurl localhost:8080liefert „Connection refused").
docker-compose.override.ymlunddocker-compose.prod.ymlnicht gemeinsam verwenden — Port-Mapping vs. Traefik schließen sich gegenseitig aus.
Nach dem Start prüfen:
docker compose ps
docker compose logs configurator
4. Site anlegen (einmalig, manuell)
docker compose exec backend bench new-site crm.localdomain \
--mariadb-user-host-login-scope='172.%.%.%' \
--db-root-password "$DB_PASSWORD" \
--admin-password <admin-passwort> \
--install-app erpnext \
--install-app crm
Danach lokal erreichbar unter http://localhost:${HTTP_PUBLISH_PORT:-8080} (Login:
Administrator / das oben gesetzte Admin-Passwort).
5. Integrationen (nur live, via docker-compose.prod.yml)
Autoheal
autoheal=true auf frontend, db, redis-cache, redis-queue (alle mit Healthcheck).
DB-Backup (shyim/docker-backup) – Schedule 5-Feld
Label auf db: type=mysql, BACKUP_SCHEDULE, Retention BACKUP_RETENTION.
Datei-Backup (Ofelia + backup-helper)
Da shyim nur named volumes sichert (sites ist ein Bind-Mount), läuft das Datei-Backup über
den idle backup-helper: Ofelia job-exec packt täglich 05:00 ein tar.gz von sites/
(Uploads, site_config.json) nach ${BACKUP_PATH}/frappe-crm-erp/sites/ (Retention laut
BACKUP_RETENTION, Default 5 Tage).
6. Warum dauert der Build so lange?
Für version-16 gibt es zwar ein vorgebautes Docker-Hub-Image (layered-Typ), dieser Stack
nutzt aber bewusst den custom-Image-Typ (nötig, um die eigenen Apps aus apps.json mit
einzubauen) — der komplett aus Source baut:
- System-Pakete installieren (Nginx, wkhtmltopdf, Chromium, MariaDB-Client, Node via nvm,
Build-Tools wie
gcc/build-essentialfür Python-Pakete wiepandas) bench initklont Frappe (Branchversion-16) sowie alle Apps ausapps.jsonfrisch per Git- Python-Dependencies pro App installieren
- Frontend-Assets bauen (Yarn/Vite) — für Frappe, ERPNext und insbesondere die Vue-basierte CRM-App der zeitaufwändigste Schritt
Es gibt keine wiederverwendbaren Docker-Hub-Layer, da diese nur für versionierte Branches existieren.
Wichtig —
CACHE_BUST: BuildKit-Secrets (apps.json) fließen bewusst nicht in den Docker-Layer-Cache-Key ein. Änderst duapps.json(neue App, anderer Branch-Stand) OHNECACHE_BUSTzu ändern, verwendet Docker stillschweigend das alte, gecachte Build-Ergebnis weiter — derbench init-Schritt läuft dann gar nicht neu!build.shsetzt deshalb bei jedem Aufruf automatisch--build-arg CACHE_BUST=$(date +%s), damitbench init(Klonen aller Apps ausapps.json) garantiert neu ausgeführt wird. System-Pakete/Node/wkhtmltopdf (die teuersten, aber selten wechselnden Schritte) bleiben davon unberührt und weiterhin gecacht.
7. Custom Apps lokal entwickeln, ohne jedes Mal neu zu bauen
Für aktive Entwicklung an einem eigenen App-Repo (z. B. LeadScraper-Google) ist ein
20–40-minütiger Rebuild pro Codeänderung unpraktikabel. Dafür gibt es das optionale
docker-compose.dev-apps.yml: es mountet den lokalen Git-Checkout des Apps direkt in die
laufenden Container, Codeänderungen sind sofort sichtbar (nach einem Service-Neustart, kein
Rebuild nötig).
Startbefehl: siehe Tabelle in Abschnitt 3 ("Lokal, mit LeadScraper-Dev-Mount") — dort auch der
wichtige Hinweis zu docker-compose.override.yml, das dabei explizit mit angegeben werden
muss.
Wichtig:
- Das Overlay ändert nur die laufenden Container, nicht das Image.
apps.json+./build.shbleiben die einzige maßgebliche, reproduzierbare Quelle für das tatsächlich gebaute (und live deployte) Image. - Vor jedem Push/Live-Deploy den echten
apps.json+Rebuild-Weg gegentesten — sonst kann der bind-gemountete Stand vom tatsächlich gebauten Image abweichen. - App-Daten (angelegte Datensätze, Einstellungen, Custom-Field-Werte) liegen unabhängig
vom Overlay immer im
sites-Volume — dieses Overlay betrifft ausschließlich App-Code. - Neue Apps ergänzen: Block in
docker-compose.dev-apps.ymlnach demleadscraper-Muster duplizieren, Pfad-Variable in.envergänzen. - Nach
backend-Neustart auchfrontendneu starten (siehe Abschnitt 9a indocs/install.md).
8. Nützliche Befehle
docker compose config -q # Konfiguration validieren
docker compose up -d
docker compose logs -f backend
docker compose exec backend bench --site crm.localdomain <command>
docker compose down
Lizenz
Copyright (C) 2026 Christian Säum – web-seo-consulting.eu
Dieses Projekt steht unter der GNU Affero General Public License, Version 3
oder (nach deiner Wahl) einer späteren Version (AGPL-3.0-or-later). Der
vollständige Lizenztext steht in der Datei LICENSE.
Du darfst die Software nutzen, weitergeben und – auch kommerziell – verkaufen.
Gibst du eine veränderte Fassung weiter oder betreibst du sie über ein
Netzwerk (z. B. als Dienst), muss deren vollständiger Quellcode ebenfalls
unter der AGPL-3.0-or-later verfügbar sein. Der Copyright-Hinweis und die
Nennung des ursprünglichen Autors dürfen nicht entfernt werden.
Diese Angabe betrifft nur die in diesem Repository enthaltenen eigenen Dateien (Konfiguration, Skripte, Anpassungen). Eingebundene Fremdsoftware und Container-Images unterliegen weiterhin ihren eigenen Lizenzen.