diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..9e7771bc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,40 @@ +# Git and Docker specific files +.git +.gitignore +.dockerignore +Dockerfile* + +# Python virtual environment and cache +.venv/ +venv/ +__pycache__/ +*.pyc +*.pyo +*.pyd +.uv_cache/ + +# Build artifacts +dist/ +build/ +*.egg-info +.eggs/ + +# IDE, editor, and OS-specific files +.idea/ +.DS_Store +*.swo +*.swp + +# Test and runtime artifacts +.pytest_cache + +# Node.js (for JS examples if any) +node_modules/ + +# Documentation (not needed in runtime) +docs/ +*.md +!README.md + +# Pre-commit +.pre-commit-config.yaml \ No newline at end of file diff --git a/DOCKER_USAGE.md b/DOCKER_USAGE.md new file mode 100644 index 00000000..c25a5498 --- /dev/null +++ b/DOCKER_USAGE.md @@ -0,0 +1,627 @@ +# Docker Usage Guide + +Complete guide for running Rogue with Docker and Docker Compose. + +## Table of Contents + +- [Building the Image](#building-the-image) +- [Running with Docker](#running-with-docker) +- [Running with Docker Compose](#running-with-docker-compose) +- [Configuration](#configuration) +- [Troubleshooting](#troubleshooting) + +--- + +## Building the Image + +### Standard Build + +```bash +docker build -t rogue-app . +``` + +### Build Options + +```bash +# No cache (fresh build) +docker build --no-cache -t rogue-app . + +# Specific platform +docker build --platform linux/amd64 -t rogue-app . + +# With version tag +docker build -t rogue-app:1.0.0 -t rogue-app:latest . +``` + +--- + +## Running with Docker + +### Default Mode (Server + TUI) + +Starts the server and launches the interactive TUI: + +```bash +docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + rogue-app +``` + +**Flags explained:** +- `-it`: Interactive terminal (required for TUI) +- `--rm`: Auto-remove container when stopped +- `-e`: Environment variable (API key) +- `-p 8000:8000`: Expose server port + +### With Persistent Storage + +```bash +docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + -v ~/.config/rogue:/root/.config/rogue \ + -v $(pwd)/.rogue:/app/.rogue \ + rogue-app +``` + +**Volumes:** +- `~/.config/rogue`: TUI configuration (API keys, preferences) +- `.rogue/`: Scenarios, reports, business context + +--- + +### Running Individual Components + +#### Server Only (Background) + +```bash +docker run -d --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + --name rogue-server \ + rogue-app \ + rogue-ai server --host 0.0.0.0 --port 8000 +``` + +**Important:** Always use `--host 0.0.0.0` in Docker containers. The default `127.0.0.1` only accepts connections from within the same container and won't allow external access. + +**Access API:** http://localhost:8000/docs + +**View logs:** +```bash +docker logs -f rogue-server +``` + +**Stop server:** +```bash +docker stop rogue-server +``` + +#### Server with Debug Mode + +```bash +docker run -d --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + --name rogue-server \ + rogue-app \ + rogue-ai server --host 0.0.0.0 --debug +``` + +--- + +#### TUI Client Only + +```bash +# First, start the server +docker run -d --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + --name rogue-server \ + rogue-app \ + rogue-ai server --host 0.0.0.0 + +# Then connect TUI +docker run -it --rm \ + --network container:rogue-server \ + rogue-app \ + rogue-ai tui +``` + +--- + +#### Web UI (Gradio) + +```bash +docker run -d --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + -p 7860:7860 \ + --name rogue-ui \ + rogue-app \ + rogue-ai ui --port 7860 +``` + +**Access Web UI:** http://localhost:7860 + +**With custom server URL:** +```bash +docker run -d --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 7860:7860 \ + --name rogue-ui \ + rogue-app \ + rogue-ai ui --port 7860 --rogue-server-url http://rogue-server:8000 +``` + +--- + +#### CLI Mode (CI/CD) + +```bash +docker run --rm \ + -e OPENAI_API_KEY="sk-..." \ + -v $(pwd)/.rogue:/app/.rogue \ + rogue-app \ + rogue-ai cli \ + --evaluated-agent-url http://host.docker.internal:10001 \ + --judge-llm openai/gpt-4o-mini \ + --business-context-file /app/.rogue/business_context.md \ + --output-report-file /app/.rogue/report.md +``` + +**Note:** Use `host.docker.internal` to access services running on your host machine. + +**Example with all options:** +```bash +docker run --rm \ + -e OPENAI_API_KEY="sk-..." \ + -v $(pwd)/.rogue:/app/.rogue \ + rogue-app \ + rogue-ai cli \ + --evaluated-agent-url http://host.docker.internal:10001 \ + --evaluated-agent-auth-type no_auth \ + --judge-llm openai/gpt-4o-mini \ + --business-context-file /app/.rogue/business_context.md \ + --input-scenarios-file /app/.rogue/scenarios.json \ + --output-report-file /app/.rogue/report.md \ + --deep-test-mode \ + --debug +``` + +--- + +#### Running with Example Agent + +```bash +docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + -p 10001:10001 \ + rogue-app \ + rogue-ai --example=tshirt_store --example-host 0.0.0.0 --example-port 10001 +``` + +--- + +## Running with Docker Compose + +The repository includes a production-ready `docker-compose.yml` that starts the server and web UI together. + +### Quick Start + +1. **Set environment variables:** + +```bash +# Option 1: Export variables +export OPENAI_API_KEY="sk-..." +export GOOGLE_API_KEY="..." +export ANTHROPIC_API_KEY="sk-..." + +# Option 2: Create .env file +cat > .env << EOF +OPENAI_API_KEY=sk-... +GOOGLE_API_KEY=... +ANTHROPIC_API_KEY=sk-... +EOF +``` + +2. **Start services:** + +```bash +docker-compose up -d +``` + +3. **Access applications:** + - **Server API:** http://localhost:8000/docs + - **Web UI:** http://localhost:7860 + +### Managing Services + +```bash +# View running services +docker-compose ps + +# View logs (all services) +docker-compose logs -f + +# View logs (specific service) +docker-compose logs -f rogue-server +docker-compose logs -f rogue-ui + +# Restart a service +docker-compose restart rogue-server + +# Stop services (containers remain) +docker-compose stop + +# Start stopped services +docker-compose start + +# Stop and remove containers +docker-compose down + +# Stop, remove containers, and delete volumes +docker-compose down -v +``` + +### Running Individual Services + +```bash +# Start only the server +docker-compose up -d rogue-server + +# Start only the UI (server must be running) +docker-compose up -d rogue-ui +``` + +### Scaling Services + +```bash +# Run multiple UI instances +docker-compose up -d --scale rogue-ui=3 +``` + +### Rebuilding After Changes + +```bash +# Rebuild images +docker-compose build + +# Rebuild and restart +docker-compose up -d --build + +# Force rebuild (no cache) +docker-compose build --no-cache +``` + +--- + +## Configuration + +### Environment Variables + +All LLM provider API keys can be set via environment variables: + +```bash +docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -e GOOGLE_API_KEY="..." \ + -e ANTHROPIC_API_KEY="sk-..." \ + -p 8000:8000 \ + rogue-app +``` + +**For docker-compose**, add them to `.env`: + +```env +OPENAI_API_KEY=sk-... +GOOGLE_API_KEY=... +ANTHROPIC_API_KEY=sk-... +``` + +### Persistent Storage + +#### Using Named Volumes + +```bash +# Create volumes +docker volume create rogue-config +docker volume create rogue-data + +# Run with volumes +docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + -v rogue-config:/root/.config/rogue \ + -v rogue-data:/app/.rogue \ + rogue-app +``` + +#### Using Host Directories + +```bash +docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + -v ~/.config/rogue:/root/.config/rogue \ + -v $(pwd)/data:/app/.rogue \ + rogue-app +``` + +**Windows (PowerShell):** +```powershell +docker run -it --rm ` + -e OPENAI_API_KEY="sk-..." ` + -p 8000:8000 ` + -v ${HOME}\.config\rogue:/root/.config/rogue ` + -v ${PWD}\data:/app/.rogue ` + rogue-app +``` + +### Port Configuration + +Change host ports if defaults are already in use: + +```bash +# Server on port 9000 instead of 8000 +docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 9000:8000 \ + rogue-app + +# Web UI on port 8080 instead of 7860 +docker run -d --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8080:7860 \ + rogue-app \ + rogue-ai ui --port 7860 +``` + +**For docker-compose**, edit `docker-compose.yml`: + +```yaml +services: + rogue-server: + ports: + - "9000:8000" # Change 9000 to your desired port +``` + +### Network Configuration + +#### Connect to External Agent + +```bash +# Agent on host machine +docker run --rm \ + -e OPENAI_API_KEY="sk-..." \ + rogue-app \ + rogue-ai cli \ + --evaluated-agent-url http://host.docker.internal:10001 +``` + +#### Agent in Docker Network + +```bash +# Create network +docker network create rogue-net + +# Run agent +docker run -d --rm \ + --network rogue-net \ + --name my-agent \ + my-agent-image + +# Run Rogue CLI +docker run --rm \ + --network rogue-net \ + -e OPENAI_API_KEY="sk-..." \ + rogue-app \ + rogue-ai cli \ + --evaluated-agent-url http://my-agent:8080 +``` + +--- + +## Troubleshooting + +### TUI Not Rendering Properly + +**Problem:** Colors, formatting, or layout broken in TUI + +**Solution:** Ensure you use `-it` flags: +```bash +docker run -it --rm rogue-app # ✅ Correct +docker run --rm rogue-app # ❌ Missing -it +``` + +--- + +### Cannot Connect to Host Services + +**Problem:** Docker container can't reach services on host machine + +**Solution:** Use `host.docker.internal`: +```bash +# ✅ Correct +--evaluated-agent-url http://host.docker.internal:10001 + +# ❌ Won't work +--evaluated-agent-url http://localhost:10001 +``` + +**Alternative:** Use host networking (Linux only): +```bash +docker run -it --rm --network host rogue-app +``` + +--- + +### Port Already in Use + +**Problem:** `bind: address already in use` + +**Solution:** Change the host port: +```bash +# Use port 9000 instead of 8000 +docker run -it --rm -p 9000:8000 rogue-app +``` + +Or stop the conflicting service: +```bash +# Find process using port 8000 +lsof -i :8000 # Linux/Mac +netstat -ano | findstr :8000 # Windows + +# Stop the process +kill # Linux/Mac +taskkill /PID /F # Windows +``` + +--- + +### Permission Denied on Volumes + +**Problem:** Cannot write to mounted directories + +**Solution 1 - Use named volumes (recommended):** +```bash +docker volume create rogue-data +docker run -v rogue-data:/app/.rogue rogue-app +``` + +**Solution 2 - Fix host directory permissions:** +```bash +# Linux/Mac +chmod -R 777 ./data +docker run -v $(pwd)/data:/app/.rogue rogue-app + +# Or match user ID +docker run --user $(id -u):$(id -g) -v $(pwd)/data:/app/.rogue rogue-app +``` + +--- + +### Health Check Failing + +**Problem:** `docker-compose` reports container unhealthy + +**Check logs:** +```bash +docker-compose logs rogue-server +``` + +**Verify health endpoint:** +```bash +docker exec rogue-server curl http://localhost:8000/api/v1/health +``` + +**Common causes:** +- Server not starting (check API key is set) +- Port conflict +- Insufficient resources + +--- + +### Container Exits Immediately + +**Problem:** Container stops right after starting + +**View logs:** +```bash +docker logs rogue-container +# or +docker-compose logs rogue-server +``` + +**Common causes:** +- Missing required environment variables (API keys) +- Command syntax error +- TUI started without `-it` flags + +--- + +### Out of Memory + +**Problem:** Container killed due to memory limits + +**Solution:** Increase Docker memory limit (Docker Desktop → Settings → Resources) + +Or set limits in docker-compose.yml: +```yaml +services: + rogue-server: + deploy: + resources: + limits: + memory: 2G +``` + +--- + +### Build Fails + +**Problem:** `docker build` errors + +**Try fresh build:** +```bash +docker build --no-cache -t rogue-app . +``` + +**Check disk space:** +```bash +docker system df +``` + +**Clean up:** +```bash +# Remove old images +docker image prune -a + +# Remove build cache +docker builder prune -a +``` + +--- + +### Slow Performance + +**Problem:** Container runs slowly + +**Solutions:** +1. **Allocate more resources** (Docker Desktop → Settings → Resources) +2. **Use local SDK cache:** + ```bash + docker run -v ~/.cache:/root/.cache rogue-app + ``` +3. **Check Docker disk usage:** + ```bash + docker system df + docker system prune + ``` + +--- + +## Quick Reference + +### Common Commands + +| Task | Command | +|------|---------| +| Build image | `docker build -t rogue-app .` | +| Run default | `docker run -it --rm -p 8000:8000 rogue-app` | +| Run server | `docker run -d -p 8000:8000 rogue-app rogue-ai server --host 0.0.0.0` | +| Run Web UI | `docker run -d -p 7860:7860 -p 8000:8000 rogue-app rogue-ai ui` | +| Start compose | `docker-compose up -d` | +| View logs | `docker-compose logs -f` | +| Stop compose | `docker-compose down` | +| Rebuild | `docker-compose up -d --build` | + +### Port Reference + +| Service | Port | URL | +|---------|------|-----| +| Server | 8000 | http://localhost:8000/docs | +| Web UI | 7860 | http://localhost:7860 | +| Example Agent | 10001 | http://localhost:10001 | diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..e2380e84 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,91 @@ +# Stage 1: Build the TUI binary from source +FROM golang:1.23-alpine AS tui-builder + +# Install make and git for the build process +RUN apk add --no-cache make git + +# Set working directory +WORKDIR /app + +# Copy the TUI source code +COPY packages/tui/ ./packages/tui/ + +# Copy version file for build metadata +COPY VERSION ./ + +# Build the TUI binary for Linux amd64 +WORKDIR /app/packages/tui +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ + -ldflags "-X github.com/rogue/tui/internal/tui.Version=v$(cat ../../VERSION)" \ + -o dist/rogue-tui ./cmd/rogue + +# Stage 2: Install Python dependencies using uv +FROM python:3.11-slim AS builder + +# Install uv +RUN pip install uv + +# Set environment variables for uv +ENV UV_NO_INTERACTION=1 \ + UV_VIRTUALENVS_CREATE=false + +# Set working directory +WORKDIR /app + +# Copy dependency files +COPY pyproject.toml uv.lock ./ + +# Copy the VERSION file (required for dynamic version) +COPY VERSION ./ + +# Copy the README.md file (required for package metadata) +COPY README.md ./ + +# Copy the SDK directory (required for the local dependency) +COPY sdks/python/ ./sdks/python/ + +# Copy the main source code (needed for editable install) +COPY rogue/ ./rogue/ + +# Install dependencies (excluding dev dependencies) +RUN uv sync --frozen --no-dev + +# Install the local packages in editable mode +RUN uv pip install -e ./sdks/python +RUN uv pip install -e . + +# Stage 3: Create the final runtime image +FROM python:3.11-slim AS final + +# Set environment variables for proper terminal rendering +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + TERM=xterm-256color \ + COLORTERM=truecolor + +# Set working directory +WORKDIR /app + +# Copy pre-installed dependencies from builder stage +COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages +COPY --from=builder /usr/local/bin /usr/local/bin + +# Copy the TUI binary from tui-builder stage +COPY --from=tui-builder /app/packages/tui/dist/rogue-tui /usr/local/bin/rogue-tui + +# Make the TUI binary executable +RUN chmod +x /usr/local/bin/rogue-tui + +# Copy the application source code +COPY . . + +# Install the local packages in editable mode (same as builder stage) +RUN pip install -e ./sdks/python +RUN pip install -e . + +# Expose port 8000 (default server port) +EXPOSE 8000 + +# Set the default command to run rogue-ai (starts server + TUI) +CMD ["rogue-ai"] + diff --git a/README.md b/README.md index ecf2195b..bf948689 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,69 @@ uvx rogue-ai cli GOOGLE_API_KEY="..." ``` +#### Option 3: Docker Installation + +Run Rogue in an isolated container environment: + +1. **Build the Docker image:** + + ```bash + git clone https://github.com/qualifire-dev/rogue.git + cd rogue + docker build -t rogue-app . + ``` + +2. **Run Rogue with Docker:** + + ```bash + # Default mode (Server + TUI) + docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -e GOOGLE_API_KEY="..." \ + -p 8000:8000 \ + rogue-app + + # With persistent configuration + docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + -v rogue-config:/root/.config/rogue \ + -v rogue-workdir:/app/.rogue \ + rogue-app + ``` + +3. **Run individual components:** + + ```bash + # Server only (background) + docker run -d --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + --name rogue-server \ + rogue-app \ + rogue-ai server + + # Web UI + docker run -d --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + -p 7860:7860 \ + rogue-app \ + rogue-ai ui + + # CLI (for CI/CD) + docker run --rm \ + -e OPENAI_API_KEY="sk-..." \ + -v $(pwd)/.rogue:/app/.rogue \ + rogue-app \ + rogue-ai cli \ + --evaluated-agent-url http://host.docker.internal:10001 \ + --judge-llm openai/gpt-4o-mini \ + --business-context-file /app/.rogue/business_context.md + ``` + +**Note:** See [DOCKER_USAGE.md](./DOCKER_USAGE.md) for detailed Docker usage, including docker-compose examples and troubleshooting. + ### Running Rogue Rogue operates on a client-server architecture where the core evaluation logic runs in a backend server, and various clients connect to it for different interfaces. @@ -413,6 +476,67 @@ Rogue's workflow is designed to be simple and intuitive, managed entirely throug --- +## 🐳 Docker Deployment + +Rogue can be fully containerized for production deployment or development isolation. + +### Quick Start + +```bash +# Build the image +docker build -t rogue-app . + +# Run (default: server + TUI) +docker run -it --rm \ + -e OPENAI_API_KEY="sk-..." \ + -p 8000:8000 \ + rogue-app +``` + +### All Components Supported + +All Rogue modes work in Docker: + +| Mode | Command | Use Case | +|------|---------|----------| +| **Default** | `docker run -it --rm -p 8000:8000 rogue-app` | Interactive TUI | +| **Server** | `docker run -d -p 8000:8000 rogue-app rogue-ai server` | Backend only | +| **Web UI** | `docker run -d -p 7860:7860 -p 8000:8000 rogue-app rogue-ai ui` | Web interface | +| **CLI** | `docker run --rm rogue-app rogue-ai cli [OPTIONS]` | CI/CD pipelines | + +### Production Setup with Docker Compose + +The repository includes a production-ready `docker-compose.yml`: + +```bash +# Set environment variables +export OPENAI_API_KEY="sk-..." + +# Start all services +docker-compose up -d + +# View status +docker-compose ps + +# View logs +docker-compose logs -f + +# Stop services +docker-compose down +``` + +**Services included:** +- `rogue-server`: Backend server with health checks (port 8000) +- `rogue-ui`: Gradio web interface (port 7860) + +**Access:** +- API Docs: http://localhost:8000/docs +- Web UI: http://localhost:7860 + +**For detailed Docker usage, see [DOCKER_USAGE.md](./DOCKER_USAGE.md)** + +--- + ## Contributing Contributions are welcome! If you'd like to contribute, please follow these steps: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..76cc31d2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,67 @@ +services: + # Rogue server - backend evaluation engine + rogue-server: + build: . + image: rogue-app:latest + command: rogue-ai server --host 0.0.0.0 --port 8000 + container_name: rogue-server + environment: + # LLM API Keys - set these in .env file or export before running + - OPENAI_API_KEY=${OPENAI_API_KEY:-} + - GOOGLE_API_KEY=${GOOGLE_API_KEY:-} + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} + ports: + - "8000:8000" + networks: + - rogue-network + volumes: + # Persistent storage for scenarios, reports, and configuration + - rogue-data:/app/.rogue + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "python -c 'import urllib.request; urllib.request.urlopen(\"http://localhost:8000/api/v1/health\")' || exit 1"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + + # Rogue Web UI - Gradio interface + rogue-ui: + image: rogue-app:latest + command: rogue-ai ui --port 7860 --rogue-server-url http://rogue-server:8000 + container_name: rogue-ui + environment: + - OPENAI_API_KEY=${OPENAI_API_KEY:-} + - GRADIO_SERVER_NAME=0.0.0.0 + ports: + - "7860:7860" + networks: + - rogue-network + volumes: + - rogue-data:/app/.rogue + depends_on: + rogue-server: + condition: service_healthy + restart: unless-stopped + + # Example: T-Shirt Store Agent (for testing) + # example-agent: + # image: rogue-app:latest + # command: rogue-ai-example-tshirt --host 0.0.0.0 --port 10001 + # container_name: tshirt-agent + # environment: + # - OPENAI_API_KEY=${OPENAI_API_KEY} + # ports: + # - "10001:10001" + # networks: + # - rogue-network + # restart: unless-stopped + +networks: + rogue-network: + driver: bridge + name: rogue-network + +volumes: + rogue-data: + name: rogue-data