services: app: build: context: . dockerfile: Dockerfile restart: unless-stopped ports: - "3010:3000" environment: DATABASE_URL: "postgresql://lms_user:${DB_PASSWORD}@db:5432/lms_db" BETTER_AUTH_SECRET: "${BETTER_AUTH_SECRET}" BETTER_AUTH_URL: "https://school.second-brain.ru" NEXT_PUBLIC_APP_URL: "https://school.second-brain.ru" RESEND_API_KEY: "${RESEND_API_KEY}" EMAIL_FROM: "${EMAIL_FROM}" BROWSER_WS_URL: "ws://browserless:3000" BROWSERLESS_TOKEN: "${BROWSERLESS_TOKEN}" PDF_MONTHLY_LIMIT: "${PDF_MONTHLY_LIMIT:-100}" depends_on: db: condition: service_healthy browserless: condition: service_started db: # ⚠️ PG18 сменил раскладку: том монтируется в /var/lib/postgresql (НЕ .../data), # кластер лежит в подкаталоге 18/docker. Мажор прода сделан 09.07.2026. # Не откатывать тег и mount по отдельности — иначе initdb на непустом томе → рестарт-луп. # В этом каталоге на Hetzner том lms-sb_postgres_data = hot-standby (тоже PG18). image: postgres:18-alpine restart: unless-stopped environment: POSTGRES_USER: lms_user POSTGRES_PASSWORD: "${DB_PASSWORD}" POSTGRES_DB: lms_db volumes: - postgres_data:/var/lib/postgresql healthcheck: test: ["CMD-SHELL", "pg_isready -U lms_user -d lms_db"] interval: 5s timeout: 5s retries: 10 browserless: image: ghcr.io/browserless/chromium restart: unless-stopped environment: TOKEN: "${BROWSERLESS_TOKEN}" CONCURRENT: "2" QUEUED: "10" TIMEOUT: "120000" mem_limit: 1g volumes: postgres_data: