# Minimal stack for Playwright E2E tests via Testcontainers # Only includes services needed for the pastebin app # # All images are self-contained (baked-in files). No host bind mounts. # Works in Docker Compose, Testcontainers, and Kubernetes. # # Usage: Started automatically by tests/e2e/global-setup.ts # Manual: docker compose -f docker-compose.e2e.yml up -d services: # PostgreSQL - Primary database for DBAL postgres: image: postgres:15-alpine environment: POSTGRES_USER: metabuilder POSTGRES_PASSWORD: metabuilder POSTGRES_DB: metabuilder POSTGRES_INITDB_ARGS: "-E UTF8" healthcheck: test: ["CMD-SHELL", "pg_isready -U metabuilder"] interval: 5s timeout: 3s retries: 10 networks: - e2e # DBAL config seeder — copies schemas and SQL templates into named volumes dbal-init: build: context: ../.. dockerfile: deployment/config/dbal/Dockerfile.init volumes: - dbal-schemas:/target/schemas/entities - dbal-templates:/target/templates/sql networks: - e2e # DBAL Daemon - C++ REST API backend (PostgreSQL only, no Redis/ES/MySQL/Mongo) dbal: build: context: ../../dbal dockerfile: production/build-config/Dockerfile args: BUILD_TYPE: Release environment: DBAL_ADAPTER: postgres DATABASE_URL: postgresql://metabuilder:metabuilder@postgres:5432/metabuilder DBAL_SCHEMA_DIR: /app/schemas/entities DBAL_TEMPLATE_DIR: /app/templates/sql DBAL_SEED_DIR: /app/seeds/database DBAL_SEED_ON_STARTUP: "true" DBAL_BIND_ADDRESS: 0.0.0.0 DBAL_PORT: 8080 DBAL_MODE: production DBAL_DAEMON: "true" DBAL_LOG_LEVEL: info DBAL_AUTO_CREATE_TABLES: "true" DBAL_ENABLE_HEALTH_CHECK: "true" DBAL_CORS_ORIGIN: "*" JWT_SECRET_KEY: "changeme-in-production" volumes: - dbal-schemas:/app/schemas/entities:ro - dbal-templates:/app/templates/sql:ro depends_on: dbal-init: condition: service_completed_successfully postgres: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:8080/health"] interval: 5s timeout: 3s retries: 15 start_period: 20s networks: - e2e # Pastebin Flask Backend - Auth + snippet storage pastebin-backend: build: context: ../.. dockerfile: frontends/pastebin/backend/Dockerfile environment: DATABASE_PATH: /app/data/snippets.db CORS_ALLOWED_ORIGINS: "*" JWT_SECRET_KEY: "changeme-in-production" DBAL_BASE_URL: "http://dbal:8080" DBAL_TENANT_ID: "pastebin" DBAL_ADMIN_TOKEN: "069e6487a710300381cd52120eab95d56d7f53beee21479cbeba9128217cbea9" volumes: - pastebin-backend-data:/app/data depends_on: dbal: condition: service_healthy healthcheck: test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:5000/health')"] interval: 5s timeout: 3s retries: 10 start_period: 10s networks: - e2e # Pastebin Next.js frontend (dev mode with Turbopack, all source baked in) pastebin: build: context: ../.. dockerfile: frontends/pastebin/Dockerfile.dev environment: NODE_ENV: development PORT: 3000 HOSTNAME: "0.0.0.0" NEXT_PUBLIC_DBAL_API_URL: /api/dbal NEXT_PUBLIC_FLASK_BACKEND_URL: /pastebin-api NEXT_TELEMETRY_DISABLED: "1" depends_on: pastebin-backend: condition: service_healthy healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://127.0.0.1:3000/pastebin"] interval: 10s timeout: 10s retries: 15 start_period: 90s networks: - e2e # nginx reverse proxy — routes /pastebin, /pastebin-api/, /api/dbal/ nginx: build: context: . dockerfile: tests/e2e/Dockerfile.nginx depends_on: pastebin: condition: service_healthy ports: - "${E2E_NGINX_PORT:-8888}:80" healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://127.0.0.1/health"] interval: 5s timeout: 3s retries: 10 networks: - e2e volumes: dbal-schemas: dbal-templates: pastebin-backend-data: networks: e2e: driver: bridge