version: '3.8' services: # app: # build: . # ports: # - "5003:5003" # volumes: # - ./storage:/app/storage # - ./instance:/app/instance # environment: # PYTHONUNBUFFERED: 1 # POSTGRES_USER: attstoreuser # POSTGRES_PASSWORD: attstorepass # POSTGRES_DB: attstoredb # DATABASE_URL: postgresql://attstoreuser:attstorepass@postgres:5432/attstoredb # STORAGE_TYPE: CLOUD_STORAGE # MINIO_ENDPOINT: http://minio:9000 # MINIO_ACCESS_KEY: minioadmin # MINIO_SECRET_KEY: minioadmin # MINIO_BUCKET: attstorebucket # MINIO_SECURE: 'false' # depends_on: # postgres: # condition: service_healthy # minio: # condition: service_healthy postgres: image: postgres:15 restart: always ports: - "5432:5432" environment: POSTGRES_USER: attstoreuser POSTGRES_PASSWORD: attstorepass POSTGRES_DB: attstoredb volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -q -U $${POSTGRES_USER:-attstoreuser} -d $${POSTGRES_DB:-attstoredb} -h 127.0.0.1 -p 5432"] interval: 5s timeout: 5s retries: 5 minio: image: minio/minio:latest command: server /data --console-address ":9001" ports: - "9000:9000" - "9001:9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin volumes: - minio-data:/data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/ready"] interval: 5s timeout: 5s retries: 5 attstore: image: ghcr.io/scribe-security/attstore:latest platform: linux/amd64 # Expose only to the internal network; Traefik will publish externally expose: - "5003" networks: - default - lbnet volumes: - ./storage:/app/storage - ./instance:/app/instance environment: PYTHONUNBUFFERED: 1 POSTGRES_USER: attstoreuser POSTGRES_PASSWORD: attstorepass POSTGRES_DB: attstoredb # Route DB connections through PgBouncer for pooling DATABASE_URL: postgresql://attstoreuser:attstorepass@pgbouncer:6432/attstoredb STORAGE_TYPE: CLOUD_STORAGE CLOUD_STORAGE_PROVIDER: MINIO MINIO_ENDPOINT: http://minio:9000 MINIO_ACCESS_KEY: minioadmin MINIO_SECRET_KEY: minioadmin MINIO_BUCKET: attstorebucket MINIO_SECURE: 'false' labels: - "traefik.enable=true" - "traefik.http.routers.attstore.rule=PathPrefix(`/`)" - "traefik.http.routers.attstore.entrypoints=web" - "traefik.http.services.attstore.loadbalancer.server.port=5003" - "traefik.http.services.attstore.loadbalancer.server.scheme=http" - "traefik.http.services.attstore.loadbalancer.sticky.cookie.name=attstore-sticky-cookie" - "traefik.docker.network=lbnet" - "traefik.http.services.attstore.loadbalancer.healthcheck.path=/healthz" - "traefik.http.services.attstore.loadbalancer.healthcheck.interval=5s" - "traefik.http.services.attstore.loadbalancer.healthcheck.timeout=2s" healthcheck: test: ["CMD-SHELL", "python - <<'PY'\nimport sys,urllib.request\ntry:\n with urllib.request.urlopen('http://localhost:5003/healthz', timeout=2) as r:\n sys.exit(0 if r.status == 200 else 1)\nexcept Exception:\n sys.exit(1)\nPY\n"] interval: 5s timeout: 3s retries: 20 depends_on: postgres: condition: service_healthy minio: condition: service_healthy pgbouncer: condition: service_started # Reverse proxy / load balancer that exposes :5003 externally traefik: image: traefik:v2.10 command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:5003" - "--log.level=INFO" ports: - "5003:5003" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" networks: - lbnet # Connection pooler for Postgres pgbouncer: image: edoburu/pgbouncer:latest expose: - "6432" environment: DB_HOST: postgres DB_PORT: 5432 DB_USER: attstoreuser DB_PASSWORD: attstorepass DB_NAME: attstoredb POOL_MODE: transaction MAX_CLIENT_CONN: 600 DEFAULT_POOL_SIZE: 20 AUTH_TYPE: plain LISTEN_ADDR: 0.0.0.0 LISTEN_PORT: 6432 depends_on: postgres: condition: service_healthy volumes: pgdata: minio-data: networks: lbnet: name: lbnet