# docker-compose.yml # Used for "clone & run" deployment scenario # Started by ./start.sh with auto-generated .env # NOTE: Run ./start.sh first to populate .env with generated secrets services: postgres: container_name: airweave-db image: postgres:16 # Uses variables from .env with fallbacks environment: POSTGRES_DB: ${POSTGRES_DB:-airweave} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} command: - "postgres" - "-c" - "max_connections=200" - "-c" - "shared_buffers=256MB" - "-c" - "effective_cache_size=1GB" ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./init-scripts:/docker-entrypoint-initdb.d:ro healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER}" ] interval: 5s timeout: 5s retries: 5 redis: container_name: airweave-redis image: redis:7-alpine ports: - "6379:6379" volumes: - redis_data:/data healthcheck: test: [ "CMD", "redis-cli", "ping" ] interval: 5s timeout: 5s retries: 5 backend: container_name: airweave-backend # Use pre-built image of latest release, or override with BACKEND_IMAGE env var for testing image: ${BACKEND_IMAGE:-ghcr.io/airweave-ai/airweave-backend:latest} # Import all variables from .env file env_file: - ../.env ports: - "8001:8001" - "9090:9090" volumes: - ../backend:/app - ../local_storage:/app/local_storage # Enable host.docker.internal on Linux (needed for webhook e2e tests) extra_hosts: - "host.docker.internal:host-gateway" # These variables override any from .env file # Required for container networking (services refer to container names, not localhost) environment: # Override any localhost references for container networking - POSTGRES_HOST=postgres - REDIS_HOST=redis - TEXT2VEC_INFERENCE_URL=http://text2vec-transformers:8080 - VESPA_URL=http://vespa - VESPA_PORT=8081 # Environment configuration (can be overridden in .env) - ENVIRONMENT=${ENVIRONMENT:-local} - LOCAL_DEVELOPMENT=${LOCAL_DEVELOPMENT:-true} # Temporal configuration - TEMPORAL_HOST=temporal - TEMPORAL_PORT=7233 - TEMPORAL_NAMESPACE=default - AUTH_ENABLED=false # Svix configuration - SVIX_URL=http://svix:8071 - SVIX_JWT_SECRET=${SVIX_JWT_SECRET} - SVIX_AUTH_TOKEN=${SVIX_AUTH_TOKEN:-} # Docling OCR (only active when DOCLING_BASE_URL is set in .env) - DOCLING_BASE_URL=${DOCLING_BASE_URL:+http://docling:5001} depends_on: postgres: condition: service_healthy redis: condition: service_healthy svix: condition: service_healthy healthcheck: test: [ "CMD", "curl", "-f", "http://localhost:8001/health/ready" ] interval: 10s timeout: 30s retries: 10 start_period: 60s restart: on-failure frontend: container_name: airweave-frontend # Use pre-built image of latest release, or override with FRONTEND_IMAGE env var for testing image: ${FRONTEND_IMAGE:-ghcr.io/airweave-ai/airweave-frontend:latest} # Profile: only start if explicitly enabled with --profile frontend # Not needed for backend-only testing (API tests, connector tests) profiles: - frontend ports: - "${FRONTEND_LOCAL_DEVELOPMENT_PORT:-8080}:8080" environment: - API_URL=http://localhost:8001 - ENABLE_AUTH=false depends_on: backend: condition: service_healthy healthcheck: test: [ "CMD", "wget", "--spider", "-q", "http://localhost:8080" ] interval: 30s timeout: 10s retries: 3 restart: on-failure connect: container_name: airweave-connect # Use pre-built image of latest release, or override with CONNECT_IMAGE env var for testing image: ${CONNECT_IMAGE:-ghcr.io/airweave-ai/airweave-connect:latest} # Profile: only start if explicitly enabled with --profile connect # Connect widget for embedded iframe integrations profiles: - connect ports: - "${CONNECT_LOCAL_DEVELOPMENT_PORT:-8082}:8082" environment: - API_URL=http://localhost:8001 - PORT=8082 depends_on: backend: condition: service_healthy healthcheck: test: [ "CMD", "wget", "--spider", "-q", "http://localhost:8082" ] interval: 30s timeout: 10s retries: 3 restart: on-failure text2vec-transformers: container_name: airweave-embeddings image: semitechnologies/transformers-inference:sentence-transformers-all-MiniLM-L6-v2 # Profile: only start if explicitly enabled with --profile local-embeddings # By default, backend uses OpenAI embeddings when OPENAI_API_KEY is set profiles: - local-embeddings ports: - "9878:8080" environment: ENABLE_CUDA: 0 WORKERS_PER_NODE: 1 healthcheck: test: [ "CMD", "wget", "--spider", "-q", "http://localhost:8080/health" ] interval: 30s timeout: 10s retries: 3 restart: on-failure temporal: container_name: airweave-temporal image: temporalio/auto-setup:1.24.2 ports: - "7233:7233" - "8233:8233" environment: - DB=postgres12 - DB_PORT=5432 - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PWD=${POSTGRES_PASSWORD} - POSTGRES_SEEDS=postgres - DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development-sql.yaml volumes: - ./temporal-config:/etc/temporal/config/dynamicconfig depends_on: postgres: condition: service_healthy healthcheck: test: [ "CMD", "tctl", "--address", "temporal:7233", "workflow", "list" ] interval: 30s timeout: 10s retries: 5 restart: on-failure temporal-init: container_name: airweave-temporal-init image: temporalio/admin-tools:1.27.2-tctl-1.18.2-cli-1.3.0 depends_on: temporal: condition: service_healthy entrypoint: ["/bin/sh", "-c"] command: - | temporal operator search-attribute create \ --name SyncId --type Keyword \ --namespace default \ --address temporal:7233 || true echo "SyncId search attribute registered" restart: "no" temporal-ui: container_name: airweave-temporal-ui image: temporalio/ui:2.26.2 ports: - "8088:8080" environment: - TEMPORAL_ADDRESS=temporal:7233 - TEMPORAL_CORS_ORIGINS=http://localhost:3000 depends_on: temporal: condition: service_healthy restart: on-failure temporal-worker: container_name: airweave-temporal-worker # Use pre-built image of latest release, or override with BACKEND_IMAGE env var for testing image: ${BACKEND_IMAGE:-ghcr.io/airweave-ai/airweave-backend:latest} # Import all variables from .env file (same as backend) env_file: - ../.env environment: # Override any localhost references for container networking - POSTGRES_HOST=postgres - REDIS_HOST=redis - TEXT2VEC_INFERENCE_URL=http://text2vec-transformers:8080 - VESPA_URL=http://vespa - VESPA_PORT=8081 # Environment configuration (can be overridden in .env) - ENVIRONMENT=${ENVIRONMENT:-local} - LOCAL_DEVELOPMENT=${LOCAL_DEVELOPMENT:-true} # Temporal configuration - TEMPORAL_HOST=temporal - TEMPORAL_PORT=7233 - TEMPORAL_NAMESPACE=default - TEMPORAL_TASK_QUEUE=airweave-sync-queue # Svix configuration - SVIX_URL=http://svix:8071 - SVIX_JWT_SECRET=${SVIX_JWT_SECRET} - SVIX_AUTH_TOKEN=${SVIX_AUTH_TOKEN:-} # Docling OCR (only active when DOCLING_BASE_URL is set in .env) - DOCLING_BASE_URL=${DOCLING_BASE_URL:+http://docling:5001} volumes: - ../backend:/app entrypoint: [ "python", "-m", "airweave.domains.temporal.worker" ] depends_on: postgres: condition: service_healthy temporal: condition: service_healthy svix: condition: service_healthy restart: on-failure # Vespa single-node for development (config server + content + container combined) vespa: container_name: airweave-vespa image: vespaengine/vespa:8 hostname: vespa ports: - "8081:8081" # Query/Document API - "19071:19071" # Config server (for deployment) volumes: - vespa_data:/opt/vespa/var - ../vespa/app:/app healthcheck: # Check config server is up (basic health for startup) test: [ "CMD", "curl", "-f", "http://localhost:19071/state/v1/health" ] interval: 10s timeout: 5s retries: 30 restart: on-failure # Vespa init container - deploys the application package automatically # This runs once after vespa is healthy, then exits vespa-init: container_name: airweave-vespa-init image: alpine:3.19 env_file: - ../.env volumes: - ../vespa/app:/app:ro - ../vespa/init-vespa.sh:/init-vespa.sh:ro entrypoint: [ "/bin/sh", "/init-vespa.sh" ] environment: - VESPA_CONFIG_SERVER=http://vespa:19071 depends_on: vespa: condition: service_healthy restart: "no" docling: container_name: airweave-docling image: ghcr.io/docling-project/docling-serve profiles: - docling ports: - "5001:5001" healthcheck: test: [ "CMD", "curl", "-sf", "http://localhost:5001/health" ] interval: 10s timeout: 10s retries: 30 start_period: 60s restart: on-failure svix: container_name: airweave-svix image: svix/svix-server ports: - "8071:8071" # Enable host.docker.internal on Linux (needed for webhook e2e tests — # Svix delivers webhooks to the test receiver running on the host) extra_hosts: - "host.docker.internal:host-gateway" environment: SVIX_WHITELIST_SUBNETS: "[0.0.0.0/0, ::/0]" WAIT_FOR: "true" SVIX_REDIS_DSN: "redis://redis:6379" SVIX_DB_DSN: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/svix" SVIX_JWT_SECRET: ${SVIX_JWT_SECRET} SVIX_QUEUE_TYPE: "redis" SVIX_CACHE_TYPE: "none" # "memory" cache causes stale endpoint lookups when messages arrive before endpoints exist depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: [ "CMD-SHELL", "svix-server healthcheck http://localhost:8071" ] interval: 5s timeout: 5s retries: 30 restart: on-failure volumes: postgres_data: redis_data: vespa_data: