From 28120aed210160e0f148d1a37385b5eddf2b201f Mon Sep 17 00:00:00 2001 From: abounoone Date: Thu, 19 Mar 2026 14:23:34 +0000 Subject: [PATCH] docs: add architecture guide and Makefile reference, fix overrides table - docs/02-setup/09-architecture.md: explain the one-image-many-containers pattern, configurator lifecycle, request flow, assets-volume requirement, and Redis durability split - docs/04-operations/02-makefile.md: document all make targets, variables, first-run checklist, and update workflow - docs/02-setup/05-overrides.md: fill in TBD entries for assets-volume, backup-cron, multi-bench, and custom-domain overrides - Makefile: add missing mariadb/redis/noproxy/backup-cron overrides to COMPOSE_OVERRIDES so make up starts a working stack Co-Authored-By: Claude Sonnet 4.6 --- Makefile | 6 ++- docs/02-setup/05-overrides.md | 15 +++--- docs/02-setup/09-architecture.md | 88 ++++++++++++++++++++++++++++++ docs/04-operations/02-makefile.md | 90 +++++++++++++++++++++++++++++++ 4 files changed, 192 insertions(+), 7 deletions(-) create mode 100644 docs/02-setup/09-architecture.md create mode 100644 docs/04-operations/02-makefile.md diff --git a/Makefile b/Makefile index e32a229b..60274e67 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,11 @@ TAG ?= v16 COMPOSE_OVERRIDES := \ -f compose.yaml \ - -f overrides/compose.assets-volume.yaml + -f overrides/compose.mariadb.yaml \ + -f overrides/compose.redis.yaml \ + -f overrides/compose.assets-volume.yaml \ + -f overrides/compose.noproxy.yaml \ + -f overrides/compose.backup-cron.yaml APPS_JSON_B64 := $(shell base64 -w 0 apps.json) diff --git a/docs/02-setup/05-overrides.md b/docs/02-setup/05-overrides.md index 0d7b6004..35b155de 100644 --- a/docs/02-setup/05-overrides.md +++ b/docs/02-setup/05-overrides.md @@ -21,9 +21,12 @@ docker compose -f compose.yaml -f overrides/compose.mariadb.yaml -f overrides/co | compose.nginxproxy-ssl.yaml | Adds acme-companion for HTTPS on port `:443` with automatic certificates | Requires `compose.nginxproxy.yaml`. Set `NGINX_PROXY_HOSTS` and `LETSENCRYPT_EMAIL`. `HTTP_PUBLISH_PORT` and `HTTPS_PUBLISH_PORT` can be set. | | **Redis** | | | | compose.redis.yaml | Adds Redis service for caching and background job queuing | -| **TBD** | **The following overrides are available but lack documentation. If you use them and understand their purpose, please consider contributing to this documentation.** | -| compose.backup-cron.yaml | | | -| compose.custom-domain-ssl.yaml | | | -| compose.custom-domain.yaml | | | -| compose.multi-bench-ssl.yaml | | | -| compose.multi-bench.yaml | | | +| **Assets / ERPNext** | | | +| compose.assets-volume.yaml | Adds a shared `assets` volume mounted to all service containers. **Required for ERPNext** — without it nginx returns 404 for all static files | Must be included whenever ERPNext or any app with compiled frontend assets is installed | +| **Backups** | | | +| compose.backup-cron.yaml | Adds [Ofelia](https://github.com/mcuadros/ofelia) cron container that runs `bench --site all backup` on a schedule | Set `BACKUP_CRONSTRING` in `.env` (default `@every 6h`). Uses Docker label-based job config on the `scheduler` container | +| **Multi-bench / Custom domain**| | | +| compose.multi-bench.yaml | Connects all services to a named `bench-network` and shared `mariadb-network`, exposes `frontend` to Traefik via `ROUTER` and `SITES_RULE` | For running multiple Frappe stacks behind a single Traefik instance. Requires `ROUTER`, `SITES_RULE`. Use with `compose.traefik.yaml` | +| compose.multi-bench-ssl.yaml | Adds HTTPS routing rules to the multi-bench setup | Use together with `compose.multi-bench.yaml` and `compose.traefik-ssl.yaml` | +| compose.custom-domain.yaml | Adds a Caddy sidecar that reverse-proxies a custom domain to `frontend:8080` and registers it with Traefik | Requires `ROUTER`, `SITES_RULE`, `BASE_SITE`. For mapping an additional hostname to a site in a multi-bench setup | +| compose.custom-domain-ssl.yaml | Adds HTTPS to the custom-domain Caddy sidecar | Use together with `compose.custom-domain.yaml` | diff --git a/docs/02-setup/09-architecture.md b/docs/02-setup/09-architecture.md new file mode 100644 index 00000000..12950d5a --- /dev/null +++ b/docs/02-setup/09-architecture.md @@ -0,0 +1,88 @@ +# Container Architecture + +## One image, many containers + +There is no single "bench container" in Frappe Docker. The classic `bench` CLI that manages everything in a bare-metal setup is **decomposed into separate processes**, each running in its own container — all from the same image. + +``` +frappe-custom:v16 (one image) + │ + ├── configurator bench set-config ... (runs once, then exits) + ├── backend gunicorn :8000 (HTTP API / page rendering) + ├── websocket node socketio.js :9000 (realtime / socket.io) + ├── queue-short bench worker --queue short,default + ├── queue-long bench worker --queue long,default,short + ├── scheduler bench schedule (Frappe's internal cron) + └── frontend nginx-entrypoint.sh (nginx reverse proxy) +``` + +External services (not from the Frappe image): + +| Service | Image | Role | +|---|---|---| +| `db` | `mariadb:11.8` | Persistent relational storage | +| `redis-cache` | `redis:6.2-alpine` | Page/session cache (no persistence) | +| `redis-queue` | `redis:6.2-alpine` | Background job queue (persistent volume) | +| `cron` | `mcuadros/ofelia` | Docker-native cron for scheduled backups | + +## Request flow + +``` +Browser → :8090 + └─► frontend (nginx) + ├─► backend:8000 HTTP/REST, page rendering + └─► websocket:9000 realtime events (socket.io) + +backend / workers + ├─► MariaDB:3306 persistent data + ├─► redis-cache:6379 caching + └─► redis-queue:6379 job queue +``` + +## The configurator + +`configurator` is the most non-obvious piece. It runs **before all other services**, writes connection addresses into `common_site_config.json` (the shared `sites` volume), and then exits with code 0. + +All other Frappe containers depend on it via: + +```yaml +depends_on: + configurator: + condition: service_completed_successfully +``` + +This is how override files inject infrastructure addresses. For example: + +```yaml +# overrides/compose.mariadb.yaml +services: + configurator: + environment: + DB_HOST: db # MariaDB container name + +# overrides/compose.redis.yaml +services: + configurator: + environment: + REDIS_CACHE: redis-cache:6379 + REDIS_QUEUE: redis-queue:6379 +``` + +Without the mariadb/redis overrides the `.env` values `DB_HOST` and `REDIS_CACHE` remain empty — Frappe starts but immediately fails to connect. + +## Why `compose.assets-volume.yaml` is mandatory for ERPNext + +The base `compose.yaml` mounts only the `sites` volume. ERPNext requires compiled JS/CSS bundles to be accessible from **all** service containers at `/home/frappe/frappe-bench/sites/assets`. + +`compose.assets-volume.yaml` adds a shared `assets` volume mounted to that path in every service. Without it nginx returns 404 for all static files. + +> The `compose.yaml` source contains an explicit comment: `# ERPNext requires local assets access (Frappe does not)`. + +## Redis: two instances, different durability + +| Instance | Purpose | Persistence | +|---|---|---| +| `redis-cache` | Page/session/query cache | None — ephemeral | +| `redis-queue` | Background job queue | `redis-queue-data` volume | + +Jobs in the queue must survive restarts, so only `redis-queue` uses a persistent volume. diff --git a/docs/04-operations/02-makefile.md b/docs/04-operations/02-makefile.md new file mode 100644 index 00000000..b9770727 --- /dev/null +++ b/docs/04-operations/02-makefile.md @@ -0,0 +1,90 @@ +# Stack management with Makefile + +The `Makefile` in the project root provides a single entry point for all common operations. It always uses the full set of override files required to run ERPNext locally. + +## Included overrides + +Every `make` command runs `docker compose` with: + +``` +compose.yaml +overrides/compose.mariadb.yaml +overrides/compose.redis.yaml +overrides/compose.assets-volume.yaml +overrides/compose.noproxy.yaml +overrides/compose.backup-cron.yaml +``` + +## Commands + +| Command | What it does | +|---|---| +| `make help` | Print all available commands with descriptions | +| `make up` | Start the full stack in detached mode | +| `make down` | Stop and remove all containers | +| `make restart` | Restart `backend`, `frontend`, `websocket` | +| `make ps` | Show container status | +| `make logs` | Stream `backend` logs live | +| `make shell` | Open `bash` in the backend container | +| `make backup` | Create a manual backup of the site | +| `make migrate` | Run `bench migrate` on the site (after app updates) | +| `make assets` | Rebuild JS/CSS bundles and restart frontend | +| `make build` | Build the `frappe-custom:v16` image from `apps.json` | +| `make update` | Full update cycle: build → recreate containers → migrate → assets | + +## Variables + +The Makefile exposes two overridable variables: + +```bash +SITE ?= erp.local # site name used in bench commands +TAG ?= v16 # image tag used in build +``` + +Override on the command line: + +```bash +make migrate SITE=mycompany.local +make build TAG=v17 +``` + +## First-run checklist + +```bash +# 1. Start the stack (MariaDB, Redis and all Frappe services) +make up + +# 2. Wait ~10 seconds for MariaDB to become healthy, then create the site +make shell +bench new-site \ + --mariadb-user-host-login-scope=% \ + --db-root-password \ + --admin-password \ + erp.local + +# 3. Install apps on the site +bench --site erp.local install-app erpnext +bench --site erp.local install-app crm +# ... other apps as needed + +exit # leave the shell + +# 4. Open http://localhost:8090 in your browser +``` + +> `DB_PASSWORD` is set in `.env`. The default value is a random string generated during project setup. + +## Updating the stack + +When `apps.json` changes (new app version or added app): + +```bash +make update +# equivalent to: make build && docker compose up -d (backend services) && make migrate && make assets +``` + +For a config-only change that doesn't require a new image: + +```bash +make down && make up +```