--- services: db: image: pgvector/pgvector:pg16 restart: unless-stopped env_file: - ./.env environment: POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?missing-postgres-password} POSTGRES_DB: ${POSTGRES_DB:-bankdocs} volumes: - pgdata:/var/lib/postgresql/data ports: # ← local only! - "5433:5432" # Map to 5433 to avoid conflict with local Postgres if any healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine restart: unless-stopped volumes: - redisdata:/data ports: - "6379:6379" # optional, for local redis-cli testing healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 5 env_file: - ./.env minio: image: minio/minio:latest restart: unless-stopped command: server /data --console-address ":9001" env_file: - ./.env environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?missing-minio-password} volumes: - miniodata:/data ports: - "9000:9000" # MinIO API - "9001:9001" # MinIO Console healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 db-init: build: context: ./api dockerfile: Dockerfile environment: DATABASE_URL: "postgresql://postgres:${POSTGRES_PASSWORD}@db:5432/bankdocs?sslmode=disable" command: > bash -c " echo 'Running DB init...' until PGPASSWORD=$$POSTGRES_PASSWORD psql -h db -U postgres -d postgres -w -c 'SELECT 1'; do echo 'Waiting for PostgreSQL...'; sleep 2 done && bundle exec rails db:create --trace || true && bundle exec rails db:migrate --trace && echo 'Waiting for vector type registration...' && sleep 5 && echo 'Creating vector column with dimensions...' && PGPASSWORD=$$POSTGRES_PASSWORD psql -h db -U postgres -d bankdocs -w -c \"ALTER TABLE document_chunks ALTER COLUMN embedding TYPE vector(1536);\" && echo 'Attempting vector index creation...' && bundle exec rails runner ' begin sql = <<-SQL.squish CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ivfflat_embedding_cosine ON document_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100) SQL ActiveRecord::Base.connection.execute(sql) puts \"Vector index created or already exists\" rescue PG::Error => e puts \"Vector index skipped: \#{e.message}\" end ' && echo 'DB init completed successfully' " env_file: - ./.env depends_on: db: condition: service_healthy restart: "no" api: build: context: ./api dockerfile: Dockerfile restart: unless-stopped command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" env_file: - ./.env environment: RAILS_ENV: ${RAILS_ENV:-development} RAILS_SERVE_STATIC_FILES: "true" RAILS_LOG_TO_STDOUT: "true" DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} REDIS_URL: redis://redis:6379/0 AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER} AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD} AWS_REGION: us-east-1 AWS_ENDPOINT_URL: http://minio:9000 AWS_S3_FORCE_PATH_STYLE: "true" MINIO_ENDPOINT: http://minio:9000 # Add SECRET_KEY_BASE, other keys from .env depends_on: db: condition: service_healthy redis: condition: service_healthy minio: condition: service_healthy db-init: # ← Key: wait for init to finish condition: service_completed_successfully volumes: - ./api:/app # ← mount for live code reload in dev (optional but super useful) ports: - "3000:3000" # ← your app at http://localhost:3000 # If web/ is separate frontend (optional – comment out if Rails serves assets) web: build: context: ./web dockerfile: Dockerfile restart: unless-stopped command: npx next dev # or preview/build/serve – adjust based on your package.json volumes: - ./web:/app ports: - "3001:3000" # common for Vite; adjust if different depends_on: - api volumes: pgdata: redisdata: miniodata: