# 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: # Connection ins Container-Netzwerk (Service-Name = Hostname) DATABASE_URL: "mysql://root:${DB_ROOT_PASSWORD}@db:3306/${DB_NAME}" JWT_SECRET: ${JWT_SECRET} JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d} ENCRYPTION_KEY: ${ENCRYPTION_KEY} NODE_ENV: production PORT: 3001 LISTEN_ADDR: 0.0.0.0 CORS_ORIGINS: ${CORS_ORIGINS:-} 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 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"