docker-compose.yml
Rama main · réplica de lectura del repositorio original.
# =========================================================================
# Maestro Platform — local infrastructure
# Brings up Postgres, MongoDB, Qdrant and Redis for development.
# The FastAPI backend and Next.js frontend run on the host (see README).
# Ollama also runs on the host (`ollama serve`) so it can use the GPU.
#
# Redis is optional locally: leave REDIS_URL unset and the rate limiter keeps
# its buckets in process memory, which is correct for a single dev worker.
#
# Every service carries a `mem_limit`, mirroring docker-compose.prod.yml. Without
# one, each container sizes its caches from the whole WSL2 VM; the four of them
# together starved the Next.js dev server on the host and froze the machine.
# The VM itself is capped separately in %USERPROFILE%\.wslconfig.
# =========================================================================
services:
postgres:
image: postgres:16-alpine
container_name: maestro-postgres
restart: unless-stopped
mem_limit: 512m
environment:
POSTGRES_USER: maestro
POSTGRES_PASSWORD: maestro
POSTGRES_DB: maestro
ports:
# Host port 5433: a native PostgreSQL service on Windows already owns 5432.
- "5433:5432"
volumes:
- ./.data/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U maestro -d maestro"]
interval: 10s
timeout: 5s
retries: 5
mongo:
image: mongo:7
container_name: maestro-mongo
restart: unless-stopped
mem_limit: 1g
# WiredTiger sizes its cache from *visible* RAM, which inside WSL2 is the
# whole VM — it ignores the cgroup limit and would get OOM-killed instead.
command: ["mongod", "--wiredTigerCacheSizeGB", "0.5"]
ports:
# Host port 27018, for the same reason Postgres uses 5433: a native
# MongoDB service (Homebrew's mongodb-community, Windows' MongoDB
# service) already owns 27017 on plenty of dev machines. It binds
# 127.0.0.1 specifically while Docker's proxy binds the wildcard, and a
# loopback-specific bind wins — so `localhost:27017` silently reaches the
# *native* server, not this container. Those installs default to
# authorization enabled, which surfaces as an unrelated-looking
# "Command update requires authentication" from the seed script.
- "27018:27017"
volumes:
# A named volume, unlike its bind-mounted siblings. WiredTiger cannot open
# an *existing* data file over Docker Desktop's VirtioFS share on macOS:
# `/data/db/WiredTiger.wt: handle-open: open` returns EPERM ("Operation not
# permitted") and mongod turns that into a fatal assertion, so the
# container crash-loops. A fresh dbpath initialises fine, which is why the
# failure only appears on the *second* start, once the files exist — and
# why it looks like a connection error from the seed script rather than a
# storage one. Postgres, Qdrant and Redis keep their bind mounts; none of
# them touches the file in the way that trips this. This also matches
# docker-compose.prod.yml, which has always used a named `mongodata`.
- mongodata:/data/db
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
qdrant:
# Pinned to the same tag as production; `latest` silently changed the storage
# format between runs and mmaps the segment store on start.
image: qdrant/qdrant:v1.18.2
container_name: maestro-qdrant
restart: unless-stopped
mem_limit: 1g
ports:
- "6333:6333" # REST
- "6334:6334" # gRPC
volumes:
- ./.data/qdrant:/qdrant/storage
# The image ships no curl/wget and its /bin/sh is dash, so CMD-SHELL cannot
# probe anything — but bash *is* installed, and its /dev/tcp redirection
# speaks enough HTTP to read Qdrant's own /readyz. That endpoint answers
# without the API key, so the same probe works in docker-compose.prod.yml.
healthcheck:
test:
- CMD
- bash
- -c
- "exec 3<>/dev/tcp/127.0.0.1/6333 && printf 'GET /readyz HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n' >&3 && grep -q '200 OK' <&3"
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: maestro-redis
restart: unless-stopped
mem_limit: 256m
# Rate-limit buckets expire in 60s, so eviction under pressure costs nothing.
command: ["redis-server", "--maxmemory", "192mb", "--maxmemory-policy", "allkeys-lru"]
ports:
- "6379:6379"
volumes:
- ./.data/redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# Only MongoDB needs one — see the comment on the mongo service. The bind-mounted
# services keep their data under ./.data, which is gitignored and safe to delete.
volumes:
mongodata: