services: bifrost: image: maximhq/bifrost:latest container_name: bifrost ports: - "${BIFROST_PORT:-8081}:8080" volumes: - ./bifrost/data:/app/data - ./bifrost/config.json:/app/data/config.json env_file: - backend/.env environment: APP_HOST: "0.0.0.0" networks: - agent-sandbox healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost:8080/health"] interval: 10s timeout: 5s retries: 3 restart: unless-stopped app: build: context: . dockerfile: backend/Dockerfile args: APP_UID: ${APP_UID:-1000} image: duckdb-data-agent:latest container_name: duckdb-data-agent ports: - "${APP_PORT:-10000}:10000" env_file: - backend/.env environment: CONTAINER_IMAGE: duckdb-agent-sidecar:latest CONTAINER_NETWORK: agent-sandbox BIFROST_BASE_URL: http://bifrost:8080 BACKEND_BASE_URL: http://duckdb-data-agent:10000 SKILLS_DIR: /app/skills SKILLS_HOST_PATH: ${SKILLS_HOST_PATH:-${PWD}/skills} PLUGINS_HOST_PATH: ${PLUGINS_HOST_PATH:-${PWD}/plugins} volumes: - /var/run/docker.sock:/var/run/docker.sock - ./skills:/app/skills - ./plugins:/app/plugins:ro - ./data:/app/data group_add: - "${DOCKER_GID:-0}" networks: - agent-sandbox depends_on: bifrost: condition: service_healthy restart: unless-stopped sidecar: build: context: ./sidecar dockerfile: Dockerfile image: duckdb-agent-sidecar:latest profiles: - sidecar # Never started directly — exists only so `docker compose build` # produces the sidecar image. The app spawns sidecar containers # on-demand via Docker SDK. networks: agent-sandbox: name: agent-sandbox external: true