version: '3.8' services: db: image: postgres:16 container_name: filaops-db environment: POSTGRES_DB: ${DB_NAME:-filaops} POSTGRES_USER: ${DB_USER:-postgres} POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme} # Loopback only: the backend reaches the database over filaops-network, # so the published port is only for tools on this host (psql, backups). ports: - "127.0.0.1:5432:5432" volumes: - filaops_pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] interval: 5s timeout: 5s retries: 5 networks: - filaops-network migrate: build: context: ./backend dockerfile: Dockerfile container_name: filaops-migrate command: ["bash", "scripts/docker-migrate.sh"] environment: DB_HOST: db DB_PORT: 5432 DB_NAME: ${DB_NAME:-filaops} DB_USER: ${DB_USER:-postgres} DB_PASSWORD: ${DB_PASSWORD:-changeme} SECRET_KEY: ${SECRET_KEY:-change-in-production} # Same as the backend, so with ENVIRONMENT=production a placeholder # SECRET_KEY or DB_PASSWORD stops here with the production message. ENVIRONMENT: ${ENVIRONMENT:-development} # PRO — set FILAOPS_LICENSE_KEY in .env to activate PRO features FILAOPS_LICENSE_KEY: ${FILAOPS_LICENSE_KEY:-} DATABASE_URL: postgresql+psycopg://${DB_USER:-postgres}:${DB_PASSWORD:-changeme}@db:5432/${DB_NAME:-filaops} depends_on: db: condition: service_healthy restart: "no" networks: - filaops-network backend: build: context: ./backend dockerfile: Dockerfile container_name: filaops-backend ports: - "8000:8000" environment: DB_HOST: db DB_PORT: 5432 DB_NAME: ${DB_NAME:-filaops} DB_USER: ${DB_USER:-postgres} DB_PASSWORD: ${DB_PASSWORD:-changeme} SECRET_KEY: ${SECRET_KEY:-change-in-production} ENVIRONMENT: ${ENVIRONMENT:-development} ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-http://localhost} FRONTEND_URL: ${FRONTEND_URL:-http://localhost} FILAOPS_VERSION: ${FILAOPS_VERSION:-} # Public Quoter: customer quote routes and self-registration. Set # ENABLE_PUBLIC_QUOTER=true in .env only if you run the Quoter. ENABLE_PUBLIC_QUOTER: ${ENABLE_PUBLIC_QUOTER:-false} # PRO — set FILAOPS_LICENSE_KEY in .env to activate PRO features FILAOPS_LICENSE_KEY: ${FILAOPS_LICENSE_KEY:-} # Email (SMTP) — set these in .env to email password reset approvals. # Email stays off, and reset requests stay pending, until SMTP_USER, # SMTP_PASSWORD and a real ADMIN_APPROVAL_EMAIL (not admin@example.com) # are set. SMTP_HOST: ${SMTP_HOST:-smtp.gmail.com} SMTP_PORT: ${SMTP_PORT:-587} SMTP_USER: ${SMTP_USER:-} SMTP_PASSWORD: ${SMTP_PASSWORD:-} SMTP_FROM_EMAIL: ${SMTP_FROM_EMAIL:-noreply@example.com} SMTP_FROM_NAME: ${SMTP_FROM_NAME:-Your Company Name} SMTP_TLS: ${SMTP_TLS:-true} ADMIN_APPROVAL_EMAIL: ${ADMIN_APPROVAL_EMAIL:-admin@example.com} depends_on: migrate: condition: service_completed_successfully db: condition: service_healthy healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5).read()"] interval: 30s timeout: 10s retries: 3 start_period: 40s volumes: - ./uploads:/app/uploads # Instance identity: install_uuid (the root of the key that encrypts # stored secrets such as the AI API key). Without a volume it is # regenerated whenever the container is recreated, and secrets saved # before that can no longer be read. - filaops_config:/var/lib/filaops/config networks: - filaops-network frontend: build: context: ./frontend dockerfile: Dockerfile args: VITE_API_URL: "" container_name: filaops-frontend ports: - "80:8080" depends_on: - backend networks: - filaops-network volumes: filaops_pgdata: name: filaops_pgdata filaops_config: name: filaops_config networks: filaops-network: name: filaops-network