networks: musehub-internal: driver: bridge services: musehub: build: . container_name: musehub ports: - "127.0.0.1:10003:10003" env_file: .env environment: DATABASE_URL: "postgresql+asyncpg://musehub:${DB_PASSWORD:-musehub}@postgres:5432/musehub" volumes: - musehub_data:/data # /tmp writable for uvicorn temp files; root filesystem is read-only. - type: tmpfs target: /tmp depends_on: postgres: condition: service_healthy networks: - musehub-internal restart: unless-stopped # Read-only root filesystem — prevents code injection and log-file exfiltration. # Explicit writable mounts: /data (object store, named volume) and /tmp (tmpfs). read_only: true deploy: resources: limits: # 1 vCPU cap prevents a runaway request from starving nginx/postgres. cpus: "1.0" # 512 MiB covers normal operation with headroom; MemoryLogMiddleware # warns at 400 MiB so we get notice before hitting the hard limit. memory: 512M reservations: cpus: "0.25" memory: 128M postgres: image: postgres:16-alpine container_name: musehub_postgres environment: POSTGRES_DB: musehub POSTGRES_USER: musehub POSTGRES_PASSWORD: "${DB_PASSWORD:-musehub}" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U musehub -d musehub"] interval: 5s timeout: 5s retries: 10 networks: - musehub-internal restart: unless-stopped # Expose on 5434 (not 5432/5433) to avoid colliding with a locally-installed # Postgres or another project's container (e.g. agentception uses 5433). # This lets the local test suite and Alembic CLI reach the DB directly: # DATABASE_URL=postgresql+asyncpg://musehub:musehub@localhost:5434/musehub # make test (the Makefile sets this automatically) # alembic upgrade head ports: - "127.0.0.1:5434:5432" deploy: resources: limits: cpus: "0.5" memory: 256M reservations: cpus: "0.1" memory: 64M volumes: musehub_data: postgres_data: