# MinIO is the S3-compatible object store that backs `tpuf`. It is the source of # truth: the engine persists every WAL segment, index epoch, and the manifest here. # The `mc` one-shot job waits for MinIO to come up, then idempotently creates the # bucket so a fresh `docker compose up -d` lands you in a ready-to-use state. # # Credentials and the bucket name come from the environment (see .env.example). # Load them first: set -a; source .env.example; set +a services: minio: image: minio/minio:latest container_name: tpuf-minio command: server /data --console-address ":9001" ports: - "9000:9000" # S3 API - "9001:9001" # web console (http://localhost:9001) environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin} volumes: - minio-data:/data healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 3s timeout: 5s retries: 20 start_period: 5s # One-shot job: wait for MinIO health, then create the `tpuf` bucket if absent. # `mc mb --ignore-existing` makes re-runs a no-op, so this is safe to repeat. createbucket: image: minio/mc:latest container_name: tpuf-createbucket depends_on: minio: condition: service_healthy environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin} TPUF_BUCKET: ${TPUF_BUCKET:-tpuf} entrypoint: > /bin/sh -c " mc alias set local http://minio:9000 \"$${MINIO_ROOT_USER}\" \"$${MINIO_ROOT_PASSWORD}\"; mc mb --ignore-existing local/\"$${TPUF_BUCKET}\"; mc ls local; echo 'bucket ready: '\"$${TPUF_BUCKET}\"; " restart: "no" # ---------------------------------------------------------------------------- # Optional load-balancer demo (profile "lb"): three identical tpuf-node query # servers behind an nginx consistent-hash load balancer that routes by namespace. # Start with: docker compose --profile lb up -d --build # All three nodes share the same MinIO, so any node can serve any namespace; the # LB just keeps each namespace on one node for cache warmth. See deploy/README.md. # ---------------------------------------------------------------------------- node0: &tpuf-node profiles: ["lb"] build: { context: ., dockerfile: deploy/Dockerfile } image: tpuf-node:local environment: &node-env NODE_ID: node0 TPUF_BACKEND: s3 TPUF_S3_ENDPOINT: http://minio:9000 TPUF_S3_ACCESS_KEY: ${MINIO_ROOT_USER:-minioadmin} TPUF_S3_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-minioadmin} TPUF_BUCKET: ${TPUF_BUCKET:-tpuf} depends_on: minio: condition: service_healthy node1: <<: *tpuf-node environment: <<: *node-env NODE_ID: node1 node2: <<: *tpuf-node environment: <<: *node-env NODE_ID: node2 # A 4th node, available for the "add a node" remap demo (deploy/remap-demo.sh). # It runs alongside the others; nginx only routes to it once the demo adds it # to the upstream and reloads. node3: <<: *tpuf-node environment: <<: *node-env NODE_ID: node3 lb: profiles: ["lb"] build: { context: ., dockerfile: deploy/Dockerfile.nginx } # bakes deploy/nginx.conf image: tpuf-lb:local container_name: tpuf-lb ports: - "8088:8080" # the namespace-routing entry point (host 8088 -> nginx 8080) depends_on: - node0 - node1 - node2 - node3 # ---------------------------------------------------------------------------- # Async indexing demo (profile "indexer"): one stateless broker fronting the # shared queue.json, plus TWO indexer daemons that claim jobs from it and run # the engine's BuildIndex out of band — turbopuffer's compute-compute separation # (docs/extensions/broker-indexer-queue.md). All three share the same MinIO, so a # job is coordinated purely through queue.json CAS: it is claimed by exactly one # indexer, and a crashed indexer's job is reclaimed after its heartbeat goes # stale. Start with: docker compose --profile indexer up -d --build # Then drive it with: deploy/queue-demo.sh # ---------------------------------------------------------------------------- broker: profiles: ["indexer"] build: { context: ., dockerfile: deploy/Dockerfile.broker } image: tpuf-broker:local container_name: tpuf-broker environment: &queue-env TPUF_BACKEND: s3 TPUF_S3_ENDPOINT: http://minio:9000 TPUF_S3_ACCESS_KEY: ${MINIO_ROOT_USER:-minioadmin} TPUF_S3_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-minioadmin} TPUF_BUCKET: ${TPUF_BUCKET:-tpuf} BROKER_ID: broker0 ports: - "8090:8090" # POST /v1/enqueue, GET /v1/queue depends_on: minio: condition: service_healthy # Two indexers, intentionally identical: they prove a job is claimed exactly # once. A short heartbeat timeout makes the crash-and-reclaim demo quick. indexer0: &tpuf-indexer profiles: ["indexer"] build: { context: ., dockerfile: deploy/Dockerfile.indexer } image: tpuf-indexer:local environment: &indexer-env <<: *queue-env WORKER_ID: indexer0 TPUF_POLL_INTERVAL: 1s TPUF_HEARTBEAT_TIMEOUT: 15s depends_on: minio: condition: service_healthy indexer1: <<: *tpuf-indexer environment: <<: *indexer-env WORKER_ID: indexer1 volumes: minio-data: