Ctrl K
ComunidadGuías…

docker-compose.local.yml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
services:
  control-plane-db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: butterbase
      POSTGRES_PASSWORD: butterbase_dev
      POSTGRES_DB: butterbase_control
    ports:
      - "5433:5432"
    volumes:
      - control-plane-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U butterbase -d butterbase_control"]
      interval: 5s
      timeout: 3s
      retries: 5
    networks:
      - butterbase

  data-plane-db:
    image: pgvector/pgvector:pg16
    environment:
      POSTGRES_USER: butterbase
      POSTGRES_PASSWORD: butterbase_dev
      POSTGRES_DB: postgres
      POSTGRES_HOST_AUTH_METHOD: md5
      POSTGRES_INITDB_ARGS: "--auth-host=md5"
    command: ["postgres", "-c", "wal_level=logical", "-c", "max_replication_slots=10", "-c", "max_wal_senders=10"]
    ports:
      - "5435:5432"
    volumes:
      - data-plane-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U butterbase -d postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
    networks:
      - butterbase

  runtime-plane-db:
    image: postgres:17
    environment:
      POSTGRES_USER: butterbase
      POSTGRES_PASSWORD: butterbase_dev
      POSTGRES_DB: butterbase_runtime_us
    ports:
      - "5437:5432"
    volumes:
      - runtime_plane_db_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U butterbase -d butterbase_runtime_us"]
      interval: 5s
      timeout: 3s
      retries: 5
    networks:
      - butterbase

  pgbouncer:
    image: edoburu/pgbouncer:latest
    ports:
      - "6432:6432"
    volumes:
      - ./infra/pgbouncer/pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro
      - ./infra/pgbouncer/userlist.txt:/etc/pgbouncer/userlist.txt:ro
    depends_on:
      data-plane-db:
        condition: service_healthy
    networks:
      - butterbase

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5
    networks:
      - butterbase

  # Pinned to a community-edition release; 2026.03+ `:latest` images require a
  # paid LOCALSTACK_AUTH_TOKEN. Self-hosters can override via the LOCALSTACK_IMAGE env.
  localstack:
    image: ${LOCALSTACK_IMAGE:-localstack/localstack:4.14.0}
    ports:
      - "4566:4566"
      - "4571:4571"
    environment:
      - LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN:-}
      - SERVICES=s3,lambda
      - DEBUG=1
      - PERSISTENCE=1
      - LAMBDA_EXECUTOR=docker
      - DOCKER_HOST=unix:///var/run/docker.sock
    volumes:
      - "./localstack-init:/etc/localstack/init/ready.d"
      - "/var/run/docker.sock:/var/run/docker.sock"
      - localstack-data:/var/lib/localstack
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:4566/_localstack/health"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 10s
    networks:
      - butterbase

  control-api:
    build:
      context: .
      dockerfile: services/control-api/Dockerfile
    ports:
      - "4000:4000"
    env_file:
      - path: .env
        required: false
    environment:
      # Override the Dockerfile's NODE_ENV=production so the prod-only env checks
      # (BUILD_RUNNER_SHARED_SECRET, BUILD_RUNNER_URL, AUTH_ENCRYPTION_KEY...) skip.
      NODE_ENV: development
      CONTROL_DB_URL: "postgresql://butterbase:butterbase_dev@control-plane-db:5432/butterbase_control"
      DATA_PLANE_DB_HOST: data-plane-db
      DATA_PLANE_DB_PORT: "5432"
      DATA_PLANE_DB_USER: butterbase
      DATA_PLANE_DB_PASSWORD: butterbase_dev
      PGBOUNCER_HOST: pgbouncer
      PGBOUNCER_PORT: "6432"
      CONTROL_API_PORT: "4000"
      AUTH_ENABLED: "false"
      AUTH_ENCRYPTION_KEY: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
      BUTTERBASE_REGIONS: us-east-1
      BUTTERBASE_REGION: us-east-1
      BUTTERBASE_PLATFORM_REGION: us-east-1
      BUTTERBASE_INTERNAL_SECRET: dev-internal-secret-change-me
      BUTTERBASE_LEASE_SIZE_USD: "1.00"
      BUTTERBASE_LEASE_REFILL_THRESHOLD_USD: "0.20"
      BUTTERBASE_LEASE_TTL_SECONDS: "300"
      NEON_RUNTIME_PROJECT_ID_US_EAST_1: "postgresql://butterbase:butterbase_dev@runtime-plane-db:5432/butterbase_runtime_us"
      NEON_DATA_PROJECT_ID_US_EAST_1: local-dev-data-project
      NEON_DATA_PROJECT_ID: local-dev-data-project
      NEON_PLATFORM_PRIMARY_URL: "postgresql://butterbase:butterbase_dev@control-plane-db:5432/butterbase_control"
      CONTROL_PLANE_URL_PLATFORM_REGION: "http://control-api:4000"
      DEV_OWNER_ID: "11111111-1111-1111-1111-111111111111"
      DEV_ADMIN_USER_ID: "22222222-2222-2222-2222-222222222222"
      NODE_OPTIONS: "--dns-result-order=ipv4first"
      S3_BUCKET_NAME: butterbase-app-storage
      AWS_REGION: us-east-1
      S3_ENDPOINT: http://localstack:4566
      S3_PUBLIC_ENDPOINT: http://localhost:4566
      S3_FORCE_PATH_STYLE: "true"
      AWS_ACCESS_KEY_ID: test
      AWS_SECRET_ACCESS_KEY: test
      REDIS_URL: redis://redis:6379
      # Per-region KV Redis (keys match BUTTERBASE_REGIONS long-form names)
      KV_REDIS_URL_US_EAST_1: redis://redis:6379
      REALTIME_MAX_LISTEN_CONNECTIONS: "100"
    depends_on:
      control-plane-db:
        condition: service_healthy
      data-plane-db:
        condition: service_healthy
      runtime-plane-db:
        condition: service_healthy
      redis:
        condition: service_healthy
      localstack:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:4000/health/ready"]
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 10s
    networks:
      - butterbase

  docs:
    build:
      context: .
      dockerfile: services/docs/Dockerfile
    ports:
      - "4321:80"
    networks:
      - butterbase

  traefik:
    image: traefik:v3.4
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - ./infra/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
      - ./infra/traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
    networks:
      - butterbase

  deno-runtime:
    image: denoland/deno:alpine-2.0.6
    working_dir: /app
    depends_on:
      pgbouncer:
        condition: service_started
      control-plane-db:
        condition: service_healthy
      runtime-plane-db:
        condition: service_healthy
      redis:
        condition: service_healthy
    ports:
      - "7133:7133"
    environment:
      - PORT=7133
      - DENO_DIR=/deno-dir
      - PGBOUNCER_HOST=pgbouncer
      - PGBOUNCER_PORT=6432
      - PGBOUNCER_USER=butterbase
      - PGBOUNCER_PASSWORD=butterbase_dev
      - BUTTERBASE_REGION=us-east-1
      - NEON_RUNTIME_PROJECT_ID_US_EAST_1=postgresql://butterbase:butterbase_dev@runtime-plane-db:5432/butterbase_runtime_us
      - CONTROL_PLANE_URL=postgresql://butterbase:butterbase_dev@control-plane-db:5432/butterbase_control
      - AUTH_ENCRYPTION_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
      - WORKER_TIMEOUT_MS=30000
      - MAX_CONCURRENT_WORKERS=100
      - REDIS_URL=redis://redis:6379
      - DO_INVOKER_URL=http://do-invoker:8787
      - DO_INVOKER_TOKEN=local-dev-do-invoker-token
    volumes:
      - ./services/deno-runtime:/app:ro
      - deno_cache:/deno-dir
    command:
      - sh
      - -c
      - |
        rm -rf /deno-dir/gen &&
        deno cache server.ts &&
        deno run \
          --allow-net \
          --allow-env \
          --allow-read=/app,/deno-dir \
          --unstable-worker-options \
          server.ts
    networks:
      - butterbase
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7133/health"]
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 10s

  # Local do-invoker shim so function↔DO round-trips work end-to-end.
  # Note: wrangler dev's local mode does not simulate WfP dispatch namespaces,
  # so the shim will 500 when attempting to dispatch. Full E2E requires
  # deploying do-invoker + a DO to a scratch CF account.
  do-invoker:
    image: node:20-alpine
    working_dir: /app
    volumes:
      - ./services/do-invoker:/app:ro
    ports:
      - "8787:8787"
    environment:
      - DO_INVOKER_TOKEN=local-dev-do-invoker-token
    command: sh -c "npm install --no-audit --no-fund && npx wrangler dev --local --ip 0.0.0.0 --port 8787"
    networks:
      - butterbase

volumes:
  control-plane-data:
  data-plane-data:
  runtime_plane_db_data:
  deno_cache:
  localstack-data:
  redis-data:

networks:
  butterbase:
    driver: bridge