Files
opencrm/docker-compose.yml
T
duffyduckandClaude Opus 5 ffeb4dbfd8 Caddy per Schalter in der .env statt per CLI-Flag
Frage aus dem Betrieb: laesst sich ein Compose-Abschnitt ueber eine Variable
in der .env zu- und abschalten, statt ihn auszukommentieren? Bedingte Bloecke
kennt Compose nicht - aber COMPOSE_PROFILES darf in der .env stehen und
aktiviert das Profil, ohne dass ein Flag noetig ist.

  COMPOSE_PROFILES=        -> Caddy wird nicht angelegt (Standard)
  COMPOSE_PROFILES=caddy   -> Caddy startet bei `docker-compose up -d` mit

Vorteil gegenueber `--profile caddy`: der Schalter wirkt auch bei down, logs
und ps, wo das Flag leicht vergessen wird und dann verwaiste Container
zurueckbleiben.

Empirisch geprueft mit einem separaten Testprojekt (compose 1.29.2): ohne den
Eintrag startete nur der ungeschuetzte Dienst, mit Eintrag beide.

Dokumentiert in .env.example, im Kommentar am caddy-Dienst und in der README.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 19:43:59 +02:00

155 lines
5.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenCRM komplettes Setup: MariaDB + Backend/Frontend + Adminer
# Konfiguration über ./.env (siehe ./.env.example)
#
# Quick-Start (Compose v2):
# cp .env.example .env # Werte anpassen (Secrets rotieren!)
# docker compose up -d # erstes Mal: holt Images, baut Backend, startet alles
# Quick-Start (Compose v1, Legacy):
# docker-compose up -d
#
# Browser:
# http://localhost:${OPENCRM_PORT} # CRM
# http://localhost:${ADMINER_PORT} # DB-UI
#
# Daten liegen alle unter ./data/* Bind-Mounts statt Volumes (auf Wunsch).
#version: '3.8'
services:
db:
image: mariadb:10.11
container_name: opencrm-db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MARIADB_DATABASE: ${DB_NAME}
MARIADB_USER: ${DB_USER}
MARIADB_PASSWORD: ${DB_PASSWORD}
ports:
# Externe Erreichbarkeit für lokale DB-Tools (TablePlus etc.).
# Auf 127.0.0.1 binden kein public exposure.
- "127.0.0.1:${DB_PORT:-3306}:3306"
volumes:
- ${DB_DATA_DIR:-./data/db}:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
start_period: 20s
interval: 10s
timeout: 5s
retries: 5
opencrm:
build:
context: .
dockerfile: backend/Dockerfile
container_name: opencrm-app
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
# DATABASE_URL wird vom entrypoint.sh aus den DB_*-Komponenten gebaut
# mit encodeURIComponent für Passwörter mit Sonderzeichen ($, !, #, @, :,
# / etc.). KEIN root für die App, sondern der App-User ${DB_USER}, den
# MariaDB beim ersten Start automatisch mit GRANT ALL PRIVILEGES auf
# ${DB_NAME}.* anlegt (über MARIADB_USER/MARIADB_PASSWORD).
DB_HOST: db
DB_PORT: 3306
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-15m}
JWT_REFRESH_EXPIRES_IN: ${JWT_REFRESH_EXPIRES_IN:-7d}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
# Siegel für das Audit-Log: signiert jeden Eintrag mit einem Schlüssel,
# der außerhalb der Datenbank liegt. Ohne Wert läuft alles normal weiter,
# nur ungesiegelt (fail-safe). AUDIT_HMAC_KEY_OLD nur beim Wechsel füllen
# (kommagetrennte Liste früherer Schlüssel).
AUDIT_HMAC_KEY: ${AUDIT_HMAC_KEY:-}
AUDIT_HMAC_KEY_OLD: ${AUDIT_HMAC_KEY_OLD:-}
NODE_ENV: production
PORT: 3001
LISTEN_ADDR: 0.0.0.0
CORS_ORIGINS: ${CORS_ORIGINS:-}
HTTPS_ENABLED: ${HTTPS_ENABLED:-false}
# SSRF-Schutz: bei Cloud-Deploys auf `true` setzen, sonst kann ein
# eingeloggter Admin via Provider-Test-Connection interne Services
# anpingen (127/10/172.16/192.168, ::1, localhost). On-Prem-Default
# ist `false`, weil Plesk/Dovecot häufig lokal laufen. Cloud-
# Metadata-Endpoints sind UNABHÄNGIG vom Flag immer geblockt.
SSRF_BLOCK_PRIVATE_IPS: ${SSRF_BLOCK_PRIVATE_IPS:-false}
RUN_SEED: ${RUN_SEED:-false}
ports:
- "${OPENCRM_PORT:-3010}:3001"
volumes:
# Bind-Mounts für persistente Daten unter ./data/
- ${UPLOADS_DIR:-./data/uploads}:/app/uploads
- ${FACTORY_DEFAULTS_DIR:-./data/factory-defaults}:/app/factory-defaults
- ${BACKUPS_DIR:-./data/backups}:/app/prisma/backups
# Auto-aktualisierter BLZ-/Bankdaten-Datensatz (Bundesbank-Bankleitzahlen)
- ${BANKDATA_DIR:-./data/bankdata}:/app/bankdata
# Optionaler Reverse-Proxy mit automatischem SSL nur fuer Betreiber OHNE
# eigenen Proxy. Wird standardmaessig NICHT angelegt.
#
# Einschalten ueber die .env (kein Auskommentieren noetig):
# COMPOSE_PROFILES=caddy
# Danach reicht wie gewohnt `docker-compose up -d`. Alternativ einmalig per
# Flag: `docker-compose --profile caddy up -d`.
# Wer nginx / Nginx Proxy Manager / Traefik davor hat, laesst das Feld leer.
caddy:
image: caddy:2-alpine
container_name: opencrm-caddy
restart: unless-stopped
profiles: ["caddy"]
depends_on:
- opencrm
environment:
DOMAIN: ${DOMAIN:-localhost}
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
# Zertifikate liegen wie alle Daten unter ./data/ nicht loeschen,
# sonst werden bei jedem Start neue Zertifikate angefordert
# (Let's-Encrypt-Limits!).
- ${CADDY_DIR:-./data/caddy}:/data
- ${CADDY_CONFIG_DIR:-./data/caddy-config}:/config
adminer:
image: adminer:latest
container_name: opencrm-adminer
restart: unless-stopped
depends_on:
- db
environment:
ADMINER_DEFAULT_SERVER: db
ADMINER_DESIGN: ${ADMINER_DESIGN:-pepa-linha}
# Adminers offizieller entrypoint linkt nur Designs, deren CSS exakt
# `adminer.css` heißt. Manche Designs (dracula, adminer-dark) haben aber
# `adminer-dark.css`. Wir machen den Symlink generisch: erstes .css im
# gewählten Design wird verlinkt. Danach übergeben wir an den originalen
# entrypoint.sh.
entrypoint:
- /bin/sh
- -c
- >
cd /var/www/html;
if [ -n "$$ADMINER_DESIGN" ] && [ -d "designs/$$ADMINER_DESIGN" ]; then
CSS=$$(ls designs/$$ADMINER_DESIGN/*.css 2>/dev/null | head -1);
if [ -n "$$CSS" ]; then
ln -sf "$$CSS" adminer.css;
touch .adminer-init;
echo "[adminer-bootstrap] Theme aktiv: $$ADMINER_DESIGN -> $$CSS";
else
echo "[adminer-bootstrap] Design '$$ADMINER_DESIGN' enthält kein CSS nutze Default";
fi;
fi;
exec entrypoint.sh docker-php-entrypoint "$$@"
- --
command: ["php", "-S", "[::]:8080", "-t", "/var/www/html"]
ports:
- "127.0.0.1:${ADMINER_PORT:-8090}:8080"