Docker-Stack: Frappe CRM + ERPNext (branch main) aufsetzen #1

Closed
opened 2026-07-25 13:50:15 +00:00 by csaeum · 1 comment
Owner

Kontext

Ablösung des alten Mautic-basierten Lead-Scrapers (wsc_py_leadscraper) durch einen Workflow, der Leads direkt in Frappe CRM anlegt. Der LeadScraper wird als Frappe Custom App (Plugin) umgesetzt, nicht als Standalone-Service per REST — dafür wird zuerst eine laufende Frappe-Instanz benötigt. CRM und ERPNext laufen bewusst in einem Stack/einer Bench, da beides Apps auf derselben Frappe-Site sind (Standard-Frappe-Architektur, kein Kompromiss).

Zugehöriges Plugin-Repo: Frappe-Projekte/LeadScraper-Google (siehe dortiges Issue "LeadScraper als Frappe Custom App statt Standalone-Service" — abhängig von diesem Stack).

Recherche-Grundlage

  • Offizielles frappe/frappe_docker-Repo geprüft: compose.yaml, Overrides (compose.mariadb.yaml, compose.redis.yaml, compose.migrator.yaml, compose.backup-cron.yaml, compose.noproxy.yaml), Doku (Build-Setup, Start-Setup, Overview, Custom-App-Konzept).
  • Wichtiger Befund: Für FRAPPE_BRANCH=main existiert kein vorgebautes Docker-Hub-Image (frappe/build:main gibt es nicht, nur versionierte Branches wie version-16). Der schnellere layered-Image-Typ scheidet damit aus — es muss der custom-Image-Typ verwendet werden (kompletter Build aus Source via images/custom/Containerfile, Basis python:slim). Erstbuild dauert ca. 20–40 Minuten.
  • Referenzprojekt Docker-Stacks/projekt-sw6 als WSC-Standardmuster herangezogen (Traefik-Labels, Autoheal-Labels, Ofelia-Cronjob-Labels, shyim/docker-backup-Labels, .env wird getrackt mit Platzhaltern, volumes/ wird ignoriert).

Entschiedene Eckpunkte

Punkt Entscheidung
Frappe-Branch main
Apps erpnext (branch main) + crm (branch main) direkt mit installiert
Image-Typ custom (kein layered, da kein Docker-Hub-Image für main existiert)
Lokaler Testzugriff Ohne Traefik, direkter Port (HTTP_PUBLISH_PORT, Default 8080)
Live-Zugriff Wie projekt-sw6: Traefik-Labels, traefik_proxy_network, Autoheal, Ofelia, shyim-Backup
MariaDB 11.8 (von Frappe für aktuelle Version getestet, bewusste Abweichung von projekt-sw6s 11.4)
Redis redis-cache + redis-queue, mit Passwortschutz (Ergänzung ggü. Frappe-Standard, konsistent zu WSC-Muster)
.env Wird getrackt (wie projekt-sw6), Platzhalter/Test-Werte lokal, echte Secrets erst live

Geplante Repo-Struktur

frappe-crm-erp/
├── AGENTS.md                    # @Projekt.md (WSC-Konvention)
├── CLAUDE.md                    # @AGENTS.md
├── Projekt.md                   # Architektur-Doku (analog projekt-sw6/Projekt.md)
├── README.md                    # Setup-Anleitung (Build → Start → Site anlegen)
├── apps.json                    # erpnext + crm, branch main
├── build.sh                     # Wrapper um den offiziellen `docker build`-Befehl
├── docker-compose.yml           # Basis: configurator, backend, frontend, websocket,
│                                 #   queue-short, queue-long, scheduler, migrator, db, redis-*
├── docker-compose.override.yml  # Lokal (autom. geladen): Port-Mapping, kein Traefik
├── docker-compose.prod.yml      # Live: Traefik-/Autoheal-/Ofelia-/Backup-Labels, PROXY_NETWORK
├── .env                         # Getrackt, Platzhalter
├── .gitignore                   # volumes/, .env.local, *.iml, dist/
└── volumes/                     # sites/, db/, redis-queue/ — bind-mounts, gitignored

apps.json

[
  { "url": "https://github.com/frappe/erpnext", "branch": "main" },
  { "url": "https://github.com/frappe/crm", "branch": "main" }
]

build.sh (kein Vendoring von frappe_docker nötig — Remote-Git-Build-Context)

docker build \
  --secret id=apps_json,src=apps.json \
  --build-arg FRAPPE_PATH=https://github.com/frappe/frappe \
  --build-arg FRAPPE_BRANCH=main \
  --tag "${CUSTOM_IMAGE:-frappe-crm-erp}:${CUSTOM_TAG:-main}" \
  --file images/custom/Containerfile \
  "https://github.com/frappe/frappe_docker.git#main"

BuildKit-Secret statt --build-arg für apps.json (sonst in Image-Historie sichtbar). Erfordert Docker Engine v23+.

docker-compose.yml Services

configurator, backend, frontend (Nginx, Ansatzpunkt für lokale/live Unterschiede), websocket, queue-short, queue-long (hier läuft später der LeadScraper-Job), scheduler (führt später scheduler_events des Plugins aus), migrator (bench --site all migrate bei jedem Start), db (MariaDB 11.8, Healthcheck, Autoheal, shyim-Backup-Labels), redis-cache + redis-queue (mit Passwortschutz), backup-helper (Ofelia-tar-Backup des sites-Volumes, analog projekt-sw6). WSC-Standard: logging.driver: json-file (max-size 10m/max-file 3), restart: unless-stopped.

docker-compose.override.yml (lokal, Default)

services:
  frontend:
    ports:
      - "${HTTP_PUBLISH_PORT:-8080}:8080"

docker-compose.prod.yml (live, explizit mit -f)

1:1 nach dem Traefik-Label-Muster aus projekt-sw6/docker-compose.yml, nur Port 8080 statt 8000.

Manuelle Schritte nach erstem Start (nicht automatisiert, analog zu Shopware-Install bei projekt-sw6)

./build.sh
docker compose up -d
docker compose exec backend bench new-site crm.local \
  --mariadb-user-host-login-scope='172.%.%.%' \
  --db-root-password "$DB_PASSWORD" \
  --admin-password <admin-passwort> \
  --install-app erpnext \
  --install-app crm

Verifikation

  • docker compose config gegen Base+Override validieren
  • ./build.sh erfolgreich (Custom-Image-Build, ~20–40 Min.)
  • docker compose up -d, configurator läuft erfolgreich durch, alle Services healthy
  • Site angelegt, http://localhost:8080 erreichbar (Login-Seite Frappe/CRM)
  • bench --site crm.local list-apps → frappe, erpnext, crm vorhanden

Nächster Schritt

Umsetzung Schritt für Schritt (Build-Skript → Compose-Dateien → .env → Doku), jeweils mit Bestätigung vor dem nächsten Schritt.

## Kontext Ablösung des alten Mautic-basierten Lead-Scrapers (`wsc_py_leadscraper`) durch einen Workflow, der Leads direkt in **Frappe CRM** anlegt. Der LeadScraper wird als **Frappe Custom App** (Plugin) umgesetzt, nicht als Standalone-Service per REST — dafür wird zuerst eine laufende Frappe-Instanz benötigt. CRM und ERPNext laufen bewusst in **einem** Stack/einer Bench, da beides Apps auf derselben Frappe-Site sind (Standard-Frappe-Architektur, kein Kompromiss). Zugehöriges Plugin-Repo: `Frappe-Projekte/LeadScraper-Google` (siehe dortiges Issue "LeadScraper als Frappe Custom App statt Standalone-Service" — abhängig von diesem Stack). ## Recherche-Grundlage - Offizielles `frappe/frappe_docker`-Repo geprüft: `compose.yaml`, Overrides (`compose.mariadb.yaml`, `compose.redis.yaml`, `compose.migrator.yaml`, `compose.backup-cron.yaml`, `compose.noproxy.yaml`), Doku (Build-Setup, Start-Setup, Overview, Custom-App-Konzept). - **Wichtiger Befund:** Für `FRAPPE_BRANCH=main` existiert **kein** vorgebautes Docker-Hub-Image (`frappe/build:main` gibt es nicht, nur versionierte Branches wie `version-16`). Der schnellere `layered`-Image-Typ scheidet damit aus — es muss der **`custom`-Image-Typ** verwendet werden (kompletter Build aus Source via `images/custom/Containerfile`, Basis `python:slim`). Erstbuild dauert ca. 20–40 Minuten. - Referenzprojekt `Docker-Stacks/projekt-sw6` als WSC-Standardmuster herangezogen (Traefik-Labels, Autoheal-Labels, Ofelia-Cronjob-Labels, shyim/docker-backup-Labels, `.env` wird getrackt mit Platzhaltern, `volumes/` wird ignoriert). ## Entschiedene Eckpunkte | Punkt | Entscheidung | |---|---| | Frappe-Branch | `main` | | Apps | `erpnext` (branch `main`) + `crm` (branch `main`) direkt mit installiert | | Image-Typ | `custom` (kein `layered`, da kein Docker-Hub-Image für `main` existiert) | | Lokaler Testzugriff | Ohne Traefik, direkter Port (`HTTP_PUBLISH_PORT`, Default `8080`) | | Live-Zugriff | Wie `projekt-sw6`: Traefik-Labels, `traefik_proxy_network`, Autoheal, Ofelia, shyim-Backup | | MariaDB | `11.8` (von Frappe für aktuelle Version getestet, bewusste Abweichung von `projekt-sw6`s `11.4`) | | Redis | `redis-cache` + `redis-queue`, **mit Passwortschutz** (Ergänzung ggü. Frappe-Standard, konsistent zu WSC-Muster) | | `.env` | Wird getrackt (wie `projekt-sw6`), Platzhalter/Test-Werte lokal, echte Secrets erst live | ## Geplante Repo-Struktur ``` frappe-crm-erp/ ├── AGENTS.md # @Projekt.md (WSC-Konvention) ├── CLAUDE.md # @AGENTS.md ├── Projekt.md # Architektur-Doku (analog projekt-sw6/Projekt.md) ├── README.md # Setup-Anleitung (Build → Start → Site anlegen) ├── apps.json # erpnext + crm, branch main ├── build.sh # Wrapper um den offiziellen `docker build`-Befehl ├── docker-compose.yml # Basis: configurator, backend, frontend, websocket, │ # queue-short, queue-long, scheduler, migrator, db, redis-* ├── docker-compose.override.yml # Lokal (autom. geladen): Port-Mapping, kein Traefik ├── docker-compose.prod.yml # Live: Traefik-/Autoheal-/Ofelia-/Backup-Labels, PROXY_NETWORK ├── .env # Getrackt, Platzhalter ├── .gitignore # volumes/, .env.local, *.iml, dist/ └── volumes/ # sites/, db/, redis-queue/ — bind-mounts, gitignored ``` ### `apps.json` ```json [ { "url": "https://github.com/frappe/erpnext", "branch": "main" }, { "url": "https://github.com/frappe/crm", "branch": "main" } ] ``` ### `build.sh` (kein Vendoring von frappe_docker nötig — Remote-Git-Build-Context) ```bash docker build \ --secret id=apps_json,src=apps.json \ --build-arg FRAPPE_PATH=https://github.com/frappe/frappe \ --build-arg FRAPPE_BRANCH=main \ --tag "${CUSTOM_IMAGE:-frappe-crm-erp}:${CUSTOM_TAG:-main}" \ --file images/custom/Containerfile \ "https://github.com/frappe/frappe_docker.git#main" ``` BuildKit-Secret statt `--build-arg` für `apps.json` (sonst in Image-Historie sichtbar). Erfordert Docker Engine v23+. ### `docker-compose.yml` Services `configurator`, `backend`, `frontend` (Nginx, Ansatzpunkt für lokale/live Unterschiede), `websocket`, `queue-short`, `queue-long` (hier läuft später der LeadScraper-Job), `scheduler` (führt später `scheduler_events` des Plugins aus), `migrator` (`bench --site all migrate` bei jedem Start), `db` (MariaDB 11.8, Healthcheck, Autoheal, shyim-Backup-Labels), `redis-cache` + `redis-queue` (mit Passwortschutz), `backup-helper` (Ofelia-tar-Backup des `sites`-Volumes, analog `projekt-sw6`). WSC-Standard: `logging.driver: json-file` (max-size 10m/max-file 3), `restart: unless-stopped`. ### `docker-compose.override.yml` (lokal, Default) ```yaml services: frontend: ports: - "${HTTP_PUBLISH_PORT:-8080}:8080" ``` ### `docker-compose.prod.yml` (live, explizit mit `-f`) 1:1 nach dem Traefik-Label-Muster aus `projekt-sw6/docker-compose.yml`, nur Port `8080` statt `8000`. ### Manuelle Schritte nach erstem Start (nicht automatisiert, analog zu Shopware-Install bei projekt-sw6) ```bash ./build.sh docker compose up -d docker compose exec backend bench new-site crm.local \ --mariadb-user-host-login-scope='172.%.%.%' \ --db-root-password "$DB_PASSWORD" \ --admin-password <admin-passwort> \ --install-app erpnext \ --install-app crm ``` ## Verifikation - [ ] `docker compose config` gegen Base+Override validieren - [ ] `./build.sh` erfolgreich (Custom-Image-Build, ~20–40 Min.) - [ ] `docker compose up -d`, `configurator` läuft erfolgreich durch, alle Services healthy - [ ] Site angelegt, `http://localhost:8080` erreichbar (Login-Seite Frappe/CRM) - [ ] `bench --site crm.local list-apps` → `frappe`, `erpnext`, `crm` vorhanden ## Nächster Schritt Umsetzung Schritt für Schritt (Build-Skript → Compose-Dateien → `.env` → Doku), jeweils mit Bestätigung vor dem nächsten Schritt.
Author
Owner

Umgesetzt, mit einer Korrektur gegenüber der ursprünglichen Planung:

frappe/frappe und frappe/erpnext haben keinen Branch main (gegen die GitHub-API geprüft) — der erste Build brach entsprechend mit InvalidRemoteException: Invalid branch or tag: main ab. Der tatsächliche aktuelle/bleeding-edge Branch heißt bei beiden develop. Alle Stellen (apps.json, build.sh, .env, docker-compose.yml, Doku) wurden entsprechend auf develop umgestellt.

Verifiziert:

  • Image-Build erfolgreich (frappe-crm-erp:develop, custom-Image-Typ)
  • Stack lokal gestartet, configurator + migrator mit Exit-Code 0
  • Site crm.local angelegt mit frappe + erpnext + crm
  • Login als Administrator end-to-end getestet (Session-Cookie + frappe.auth.get_logged_user bestätigt)
  • Bind-Mount-Volume-Muster (./volumes/*) empirisch gegen docker compose down --volumes --rmi all geprüft: Daten bleiben erhalten

Commit: a7600be — Doku unter docs/install.md (Schritt-für-Schritt für spätere Live-Installation).

**Umgesetzt, mit einer Korrektur gegenüber der ursprünglichen Planung:** `frappe/frappe` und `frappe/erpnext` haben keinen Branch `main` (gegen die GitHub-API geprüft) — der erste Build brach entsprechend mit `InvalidRemoteException: Invalid branch or tag: main` ab. Der tatsächliche aktuelle/bleeding-edge Branch heißt bei beiden `develop`. Alle Stellen (`apps.json`, `build.sh`, `.env`, `docker-compose.yml`, Doku) wurden entsprechend auf `develop` umgestellt. Verifiziert: - Image-Build erfolgreich (`frappe-crm-erp:develop`, custom-Image-Typ) - Stack lokal gestartet, `configurator` + `migrator` mit Exit-Code 0 - Site `crm.local` angelegt mit `frappe` + `erpnext` + `crm` - Login als `Administrator` end-to-end getestet (Session-Cookie + `frappe.auth.get_logged_user` bestätigt) - Bind-Mount-Volume-Muster (`./volumes/*`) empirisch gegen `docker compose down --volumes --rmi all` geprüft: Daten bleiben erhalten Commit: a7600be — Doku unter `docs/install.md` (Schritt-für-Schritt für spätere Live-Installation).
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Docker-Stacks/frappe-crm-erp#1
No description provided.