services: redis: container_name: redis profiles: ["core", "full"] image: docker.io/valkey/valkey:8-alpine command: valkey-server --save 30 1 --loglevel warning restart: unless-stopped volumes: - redis-data:/data cap_drop: - ALL cap_add: - SETGID - SETUID - DAC_OVERRIDE logging: driver: "json-file" options: max-size: "1m" max-file: "1" networks: - agentic-seek-net searxng: container_name: searxng profiles: ["core", "full"] image: docker.io/searxng/searxng:latest restart: unless-stopped ports: - "${SEARXNG_PORT:-8080}:8080" volumes: - ./searxng:/etc/searxng:rw,z environment: - SEARXNG_BASE_URL=${SEARXNG_BASE_URL:-http://localhost:8080/} - SEARXNG_SECRET_KEY=${SEARXNG_SECRET_KEY} - GRANIAN_WORKERS=4 - GRANIAN_BLOCKING_THREADS=4 cap_add: - CHOWN - SETGID - SETUID logging: driver: "json-file" options: max-size: "1m" max-file: "1" depends_on: - redis networks: - agentic-seek-net frontend: container_name: frontend profiles: ["core", "full"] build: context: ./frontend dockerfile: Dockerfile.frontend ports: - "3000:3000" volumes: - ./frontend/agentic-seek-front/src:/app/src:rw,z - ./screenshots:/app/screenshots environment: - NODE_ENV=development - CHOKIDAR_USEPOLLING=true - REACT_APP_BACKEND_URL=${REACT_APP_BACKEND_URL:-http://localhost:7777} networks: - agentic-seek-net backend: container_name: backend profiles: ["backend", "full"] build: context: . dockerfile: Dockerfile.backend ports: # Publish on the host loopback only. The agent runs shell commands, so even # with the API token required, keep it off the network by default. To expose # it intentionally, change this to "0.0.0.0:${BACKEND_PORT}:${BACKEND_PORT}", # add the host to AGENTICSEEK_ALLOWED_HOSTS and put it behind TLS. - 127.0.0.1:${BACKEND_PORT:-7777}:${BACKEND_PORT:-7777} volumes: # Agent workspace: agent-run code (unprivileged uid) may write only here and /tmp. - ${WORK_DIR}:/opt/workspace # Runtime data (logs, screenshots, sessions, API token) — root-only (0700). - agent-runtime:/opt/agent-runtime # NET_ADMIN lets the entrypoint block loopback for agent-run code, which # would otherwise reach root-owned chromedriver/Chrome DevTools ports. cap_add: - NET_ADMIN command: python3 api.py environment: - SEARXNG_BASE_URL=${SEARXNG_BASE_URL:-http://searxng:8080} - REDIS_URL=${REDIS_BASE_URL:-redis://redis:6379/0} - WORK_DIR=/opt/workspace - AGENT_RUNTIME_DIR=/opt/agent-runtime - BACKEND_PORT=${BACKEND_PORT} # Bind 0.0.0.0 *inside* the container so the loopback-only published port # (see the "ports" mapping above) can reach it. The host only exposes the # port on 127.0.0.1, so it is not reachable from the network by default. - BACKEND_HOST=0.0.0.0 - FRONTEND_ORIGINS=${FRONTEND_ORIGINS:-http://localhost:3000} - DOCKER_INTERNAL_URL=http://host.docker.internal # API token; auto-generated into /opt/agent-runtime/api_token when empty. - AGENTICSEEK_API_TOKEN=${AGENTICSEEK_API_TOKEN:-} - AGENTICSEEK_ALLOWED_HOSTS=${AGENTICSEEK_ALLOWED_HOSTS:-} # Agent-run code runs as this uid; match the owner of WORK_DIR on Linux. - AGENTICSEEK_EXEC_UID=${AGENTICSEEK_EXEC_UID:-1000} - AGENTICSEEK_EXEC_GID=${AGENTICSEEK_EXEC_GID:-} - OPENAI_API_KEY=${OPENAI_API_KEY} - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY} - OPENROUTER_API_KEY=${OPENROUTER_API_KEY} - TOGETHER_API_KEY=${TOGETHER_API_KEY} - GOOGLE_API_KEY=${GOOGLE_API_KEY} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - HUGGINGFACE_API_KEY=${HUGGINGFACE_API_KEY} - DSK_DEEPSEEK_API_KEY=${DSK_DEEPSEEK_API_KEY} networks: - agentic-seek-net extra_hosts: - "host.docker.internal:host-gateway" volumes: redis-data: chrome_profiles: agent-runtime: networks: agentic-seek-net: driver: bridge