/ docker-compose.yml
docker-compose.yml
  1  # Ag3ntum Docker Compose Configuration
  2  #
  3  # Environment Variables:
  4  #   AG3NTUM_IMAGE_TAG  - Docker image tag (default: latest)
  5  #   AG3NTUM_API_PORT   - API port on host (default: 40080)
  6  #   AG3NTUM_WEB_PORT   - Web UI port on host (default: 50080)
  7  #   AG3NTUM_REDIS_PORT - Redis debug port on host (default: 46379)
  8  #   AG3NTUM_UID_MODE   - UID mapping mode: "isolated" (default) or "direct"
  9  #   AG3NTUM_MODE       - Deployment mode: "prod" (default) or "dev"
 10  #
 11  # Deployment Modes:
 12  #   prod (default): Web container serves pre-built static bundle (fast startup)
 13  #   dev:            Web container runs Vite dev server with HMR (see docker-compose.dev.yml)
 14  #
 15  # Both modes use two ports:
 16  #   - WEB_PORT (50080): Web UI
 17  #   - API_PORT (40080): API endpoint
 18  #
 19  # UID Security Modes:
 20  #   isolated (default): UIDs 50000-60000, doesn't map to host users (multi-tenant safe)
 21  #   direct:             UIDs 1000-65533, maps to host users (dev/single-tenant)
 22  #
 23  # Usage:
 24  #   ./run.sh build           # Build and start (handles permissions automatically)
 25  #   docker compose up -d     # Start existing containers
 26  #   docker compose down      # Stop containers
 27  #
 28  # See QUICK-START-GUIDE.md for detailed deployment instructions.
 29  
 30  services:
 31    ag3ntum-api:
 32      image: ag3ntum:${AG3NTUM_IMAGE_TAG:-latest}
 33      build: .
 34      # Runs as ag3ntum_api (UID 45045) as defined in Dockerfile
 35      # Do NOT override with user: directive - breaks sudo inside container
 36      entrypoint: ["/entrypoint-api.sh"]
 37      command:
 38        - python
 39        - -m
 40        - uvicorn
 41        - src.api.main:app
 42        - --host=0.0.0.0
 43        - --port=40080
 44      environment:
 45        AG3NTUM_ROOT: "/"
 46        PYTHONPATH: "/"
 47        # UID Security Mode: "isolated" (default, multi-tenant safe) or "direct" (host mapping)
 48        AG3NTUM_UID_MODE: "${AG3NTUM_UID_MODE:-isolated}"
 49      volumes:
 50        - ./config:/config
 51        - ./data:/data
 52        - ./logs:/logs
 53        - ./src:/src:ro
 54        - ./users:/users
 55        - ./prompts:/prompts:ro
 56        - ./skills:/skills:ro
 57        - ./tools:/tools:ro
 58        - ./tests:/tests:ro
 59        - ./scripts:/scripts:ro
 60        - ./auto-generated:/auto-generated:ro
 61      ports:
 62        - "${AG3NTUM_API_PORT:-40080}:40080"
 63      cap_add:
 64        - SYS_ADMIN
 65        # CAP_SETUID and CAP_SETGID required for privilege dropping in sandbox
 66        # Security is enforced at application level in src/core/uid_security.py:
 67        # - Root (UID 0) is ALWAYS blocked
 68        # - System accounts (1-999) are blocked
 69        # - UIDs must be in configured range (isolated: 2000-60000, direct: 1000-65533)
 70        # - Session UID enforcement prevents cross-user access
 71        - SETUID
 72        - SETGID
 73        # CAP_CHOWN required for setting workspace ownership to sandbox user's UID
 74        # This allows session directories to be accessible by the sandboxed process
 75        - CHOWN
 76      security_opt:
 77        - apparmor:unconfined
 78        # Container-level seccomp: default-deny allowlist permitting bwrap, privilege
 79        # management, and standard operations. Blocks ptrace, kexec, reboot, etc.
 80        - seccomp:./config/security/seccomp-container.json
 81      depends_on:
 82        - redis
 83      restart: unless-stopped
 84  
 85    ag3ntum-web:
 86      image: ag3ntum:${AG3NTUM_IMAGE_TAG:-latest}
 87      build: .
 88      # Production mode (default): serves pre-built static bundle from /web_dist.
 89      # Dev mode overrides command/volumes via docker-compose.dev.yml for Vite HMR.
 90      entrypoint: ["/entrypoint-web.sh"]
 91      command:
 92        - python3
 93        - -m
 94        - uvicorn
 95        - src.web_frontend_server:app
 96        - --host=0.0.0.0
 97        - --port=50080
 98      environment:
 99        AG3NTUM_ROOT: "/"
100        PYTHONPATH: "/"
101        AG3NTUM_MODE: "${AG3NTUM_MODE:-prod}"
102      volumes:
103        - ./config:/config
104        - ./logs:/logs
105        - ./src:/src:ro
106        # Mount generated config.yaml into the static bundle so port/hostname
107        # changes take effect on restart without requiring a full image rebuild.
108        - ./src/web_terminal_client/public/config.yaml:/web_dist/config.yaml:ro
109      ports:
110        - "${AG3NTUM_WEB_PORT:-50080}:50080"
111      depends_on:
112        - ag3ntum-api
113        - redis
114      restart: unless-stopped
115  
116    redis:
117      image: redis:7-alpine
118      command: redis-server /usr/local/etc/redis/redis.conf
119      volumes:
120        - ./config/redis.conf:/usr/local/etc/redis/redis.conf:ro
121      ports:
122        - "127.0.0.1:${AG3NTUM_REDIS_PORT:-46379}:6379"
123      restart: unless-stopped
124  
125  # Named volumes: web_node_modules defined in docker-compose.dev.yml (dev mode only)