name: nebula # ───────────────────────────────────────────────────────────── # Diese Datei veroeffentlicht nur einen einzigen Port, und den auf dem # Loopback: den der Anwendung. Die Datenbank bleibt im Docker-Netz. # # 1) Alles im Container (Server wie Entwicklung): # docker compose --profile full up -d --build # # 2) Standalone-Entwicklung – Datenbank im Container, App auf dem Host. # Dafuer muss Postgres auf dem Host erreichbar sein, also mit dem # Entwicklungs-Overlay (oder kurz: npm run docker:db): # docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d db # npm run dev # # 3) Server ohne jede Portfreigabe, hinter einem Reverse Proxy im # gemeinsamen Docker-Netz: siehe docker-compose.server.yml # # Optionales DB-Webinterface: # docker compose --profile tools up -d adminer → http://localhost:8080 # ───────────────────────────────────────────────────────────── services: db: image: postgres:17-alpine container_name: nebula-db restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-nebula} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-nebula} POSTGRES_DB: ${POSTGRES_DB:-nebula} # Deterministische Sortierung unabhaengig vom Host-Locale POSTGRES_INITDB_ARGS: "--encoding=UTF8" # Absichtlich keine Portfreigabe: die Anwendung erreicht die Datenbank im # Container ueber "db:5432", und backup.sh geht ueber "docker exec". Nach # aussen muss hier nichts. Wer die Datenbank vom Host aus braucht – fuer # "npm run dev" oder psql – nimmt docker-compose.dev.yml dazu. volumes: - nebula-db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-nebula} -d ${POSTGRES_DB:-nebula}"] interval: 5s timeout: 5s retries: 20 start_period: 10s app: profiles: ["full"] build: context: . dockerfile: Dockerfile image: nebula-app:latest container_name: nebula-app restart: unless-stopped depends_on: db: condition: service_healthy environment: DATABASE_URL: postgresql://${POSTGRES_USER:-nebula}:${POSTGRES_PASSWORD:-nebula}@db:5432/${POSTGRES_DB:-nebula}?schema=public # Unbedingt in der .env ueberschreiben – verschluesselt die Git-Tokens. APP_SECRET: ${APP_SECRET:-nebula-dev-secret-bitte-in-der-env-aendern} # Name und oeffentliche Adresse. APP_URL bestimmt die WebAuthn-rpID – # passt sie nicht zur aufgerufenen Adresse, scheitern Passkeys. APP_NAME: ${APP_NAME:-Nebula} APP_TAGLINE: ${APP_TAGLINE:-Vibe Coding} APP_URL: ${APP_URL:-http://localhost:3000} SESSION_TTL_DAYS: ${SESSION_TTL_DAYS:-30} GIT_API_TIMEOUT_MS: ${GIT_API_TIMEOUT_MS:-15000} NOTIFY_TIMEOUT_MS: ${NOTIFY_TIMEOUT_MS:-10000} SMTP_HOST: ${SMTP_HOST:-} SMTP_PORT: ${SMTP_PORT:-587} SMTP_SECURE: ${SMTP_SECURE:-} SMTP_USER: ${SMTP_USER:-} SMTP_PASSWORD: ${SMTP_PASSWORD:-} SMTP_FROM: ${SMTP_FROM:-} GIT_ALLOW_LOOPBACK: ${GIT_ALLOW_LOOPBACK:-false} GIT_BLOCK_PRIVATE: ${GIT_BLOCK_PRIVATE:-false} GIT_ALLOWED_HOSTS: ${GIT_ALLOWED_HOSTS:-} NODE_ENV: production PORT: 3000 HOSTNAME: 0.0.0.0 ports: # Nur auf dem Loopback: nach draussen kommt man ueber den Reverse Proxy. # Docker schreibt seine Freigaben an ufw vorbei direkt in iptables – eine # Bindung auf 0.0.0.0 stuende also im Netz, auch bei aktiver Firewall. # Ganz ohne Host-Port: docker-compose.server.yml. - "${APP_PORT:-127.0.0.1:3000}:3000" adminer: profiles: ["tools"] image: adminer:latest container_name: nebula-adminer restart: unless-stopped depends_on: db: condition: service_healthy environment: ADMINER_DEFAULT_SERVER: db ADMINER_DESIGN: dracula ports: - "${ADMINER_PORT:-127.0.0.1:8080}:8080" volumes: nebula-db-data: name: nebula-db-data