From 01b5beaf7372dbc6a73b87b5d9afde7be140a88d Mon Sep 17 00:00:00 2001 From: Shashank Date: Sat, 24 Jan 2026 09:29:14 +0000 Subject: [PATCH 1/2] Add Docker configuration for OpenUI --- .dockerignore | 63 ++++++++++++++++++++++++++++++ .env.example | 80 +++++++++++++++++++++++++++++++++++++++ Dockerfile | 72 +++++++++++++++++++++++++++++++++++ docker-compose.full.yml | 75 ++++++++++++++++++++++++++++++++++++ docker-compose.hybrid.yml | 78 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 368 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 Dockerfile create mode 100644 docker-compose.full.yml create mode 100644 docker-compose.hybrid.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0d243fc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,63 @@ +# Dependencies +node_modules/ +**/node_modules/ +# Keep bun.lock for Docker builds +# *.lock + +# Build outputs (will be generated in container) +dist/ +client/dist/ + +# State and runtime data +.openui/ +.env +.env.local + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store +*.sublime-* + +# Git +.git/ +.gitignore + +# CI/CD +.github/ +.gitlab-ci.yml + +# Documentation (keep README.md) +*.md +!README.md + +# Test files +**/*.test.ts +**/*.test.js +**/__tests__/ +**/coverage/ + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Temporary files +*.tmp +.cache/ + +# Claude Code plugin (installed at runtime) +claude-code-plugin/ + +# Docker files (don't include in image) +Dockerfile* +docker-compose*.yml +.dockerignore + +# Plans and development files +.claude/ +plans/ diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..3b7ff9d --- /dev/null +++ b/.env.example @@ -0,0 +1,80 @@ +# ============================================ +# OpenUI Docker Configuration +# ============================================ + +# Server Configuration +NODE_ENV=production +PORT=6968 +OPENUI_QUIET=1 + +# ============================================ +# Project Directory (HYBRID MODE ONLY) +# ============================================ +# Absolute path to your project directory on host +# This path must match both host and container mount points +# PROJECT_DIR=/path/to/your/projects + +# Example: PROJECT_DIR=/home/user/code +# Example: PROJECT_DIR=$(pwd)/projects + +# ============================================ +# Git Configuration +# ============================================ +# Used for commits made by AI agents +GIT_AUTHOR_NAME=Your Name +GIT_AUTHOR_EMAIL=your.email@example.com + +# ============================================ +# API Keys (OPTIONAL) +# ============================================ +# Only required if your AI tools need API access +# ANTHROPIC_API_KEY=your_anthropic_api_key_here +# GITHUB_TOKEN=your_github_token_here +# LINEAR_API_KEY=your_linear_api_key_here + +# ============================================ +# Deployment Mode +# ============================================ +# Options: full | hybrid +DEPLOYMENT_MODE=full + +# ============================================ +# Claude Code Configuration (FULL MODE ONLY) +# ============================================ +# Claude Code will be auto-installed in container +# But you can specify a version or custom install path +# CLAUDE_VERSION=latest +# CLAUDE_INSTALL_DIR=/usr/local/bin + +# ============================================ +# Resource Limits (FULL MODE ONLY) +# ============================================ +# Adjust based on your host's available resources +MAX_CPUS=4 +MAX_MEMORY=4G + +# ============================================ +# Hybrid Mode Agent Execution (HYBRID MODE ONLY) +# ============================================ +# How should agents be spawned in hybrid mode? +# Options: ssh | docker-cli | named-pipe +# HYBRID_AGENT_SPAWN_METHOD=ssh + +# SSH configuration for ssh method +# SSH_HOST=localhost +# SSH_USER=root +# SSH_PORT=22 + +# ============================================ +# Volume Configuration +# ============================================ +# Where to persist OpenUI state +STATE_VOLUME_NAME=openui-state +PLUGIN_VOLUME_NAME=openui-plugin + +# ============================================ +# Development Settings (OPTIONAL) +# ============================================ +# Enable for debugging +# DEBUG=1 +# LOG_LEVEL=verbose diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..154b869 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,72 @@ +# Stage 1: Build frontend +FROM oven/bun:1.0.30-alpine AS builder + +WORKDIR /app + +# Install build dependencies +RUN apk add --no-cache \ + git \ + python3 \ + make \ + g++ + +# Copy package files +COPY package.json bun.lock ./ +COPY client/package.json client/bun.lock* ./client/ + +# Install dependencies +RUN bun install +WORKDIR /app/client +RUN bun install +WORKDIR /app + +# Copy source code +COPY . . + +# Build frontend +WORKDIR /app/client +RUN bun run build + +# Stage 2: Production image +FROM oven/bun:1.0.30-alpine + +WORKDIR /app + +# Install runtime dependencies +RUN apk add --no-cache \ + bash \ + git \ + python3 \ + npm \ + curl + +# Copy backend dependencies +COPY package.json bun.lock ./ +RUN bun install --production + +# Copy built frontend from builder +COPY --from=builder /app/client/dist ./client/dist + +# Copy server and bin directories +COPY server ./server +COPY bin ./bin + +# Create directories for runtime +RUN mkdir -p /app/.openui && \ + chmod 755 /app/bin/openui.ts + +# Expose ports +# 6968: Backend server + WebSocket +EXPOSE 6968 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:6968/api/config || exit 1 + +# Set environment defaults +ENV NODE_ENV=production \ + PORT=6968 \ + OPENUI_QUIET=1 + +# Run the server +CMD ["bun", "run", "server/index.ts"] diff --git a/docker-compose.full.yml b/docker-compose.full.yml new file mode 100644 index 0000000..f818e2a --- /dev/null +++ b/docker-compose.full.yml @@ -0,0 +1,75 @@ +version: '3.9' + +services: + openui: + build: + context: . + dockerfile: Dockerfile + container_name: openui-full + restart: unless-stopped + + # Port mappings + ports: + - "6968:6968" # Backend + WebSocket + + # Project directory mounts + # Mount your projects here so agents can work on them + volumes: + # State persistence + - openui-state:/root/.openui + + # Plugin directory + - openui-plugin:/root/.openui/claude-code-plugin + + # Project directories - MOUNT YOUR PROJECTS HERE + # Examples: + - ./projects:/projects + + # Or mount specific projects: + # - /path/to/project1:/projects/project1 + # - /path/to/project2:/projects/project2 + + # Git credentials for cloning + - ${HOME}/.gitconfig:/root/.gitconfig:ro + - ${HOME}/.ssh:/root/.ssh:ro + + # Environment variables + environment: + - NODE_ENV=production + - PORT=6968 + - LAUNCH_CWD=/projects + - OPENUI_QUIET=1 + + # Git configuration + - GIT_AUTHOR_NAME=${GIT_AUTHOR_NAME:-OpenUI} + - GIT_AUTHOR_EMAIL=${GIT_AUTHOR_EMAIL:-openui@local} + + # Claude Code API key (if using Claude API) + - ${ANTHROPIC_API_KEY:+ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}} + + # Working directory inside container + working_dir: /projects + + # Network mode + network_mode: bridge + + # Resource limits (optional but recommended) + deploy: + resources: + limits: + cpus: '4' + memory: 4G + reservations: + cpus: '1' + memory: 1G + + # Keep container running + stdin_open: true + tty: true + +volumes: + # Persist OpenUI state and plugin + openui-state: + driver: local + openui-plugin: + driver: local diff --git a/docker-compose.hybrid.yml b/docker-compose.hybrid.yml new file mode 100644 index 0000000..41e68db --- /dev/null +++ b/docker-compose.hybrid.yml @@ -0,0 +1,78 @@ +version: '3.9' + +# HYBRID MODE - OpenUI UI in container, AI agents on host +# NOTE: This is an advanced configuration that requires additional setup. +# The sessionManager.ts needs to be modified to spawn agents via SSH, Docker CLI, or IPC. +# See README for details on implementing hybrid mode agent spawning. + +services: + openui: + build: + context: . + dockerfile: Dockerfile + container_name: openui-hybrid + restart: unless-stopped + + # Port mappings + ports: + - "6968:6968" # Backend + WebSocket + + # Volume mounts for hybrid mode + volumes: + # State persistence + - openui-state:/root/.openui + + # Plugin directory (synced with host) + - ${HOME}/.openui/claude-code-plugin:/root/.openui/claude-code-plugin + + # Project directories - MUST MATCH HOST PATHS + # This allows agents to run on host but UI sees same files + - ${PROJECT_DIR:-./projects}:${PROJECT_DIR:-/projects} + + # Docker socket for spawning agents on host (optional, for Docker CLI method) + - /var/run/docker.sock:/var/run/docker.sock + + # Host binary access (if AI tools are installed in these locations) + # Uncomment and adjust paths based on your host setup: + # - /usr/local/bin/claude:/usr/local/bin/claude:ro + # - /usr/local/bin/opencode:/usr/local/bin/opencode:ro + + # Git credentials + - ${HOME}/.gitconfig:/root/.gitconfig:ro + - ${HOME}/.ssh:/root/.ssh:ro + + # Environment variables + environment: + - NODE_ENV=production + - PORT=6968 + - LAUNCH_CWD=${PROJECT_DIR:-/projects} + - OPENUI_QUIET=1 + + # Hybrid mode flag (for future use in sessionManager) + - OPENUI_HYBRID_MODE=true + + # Path to host tools (accessed via mount) - adjust as needed + # - CLAUDE_BIN_PATH=/usr/local/bin/claude + # - OPENCODE_BIN_PATH=/usr/local/bin/opencode + + # Working directory + working_dir: ${PROJECT_DIR:-/projects} + + # Network mode - use host to access host services + # Alternatively, use 'bridge' and configure SSH to host + network_mode: host + + # Extra capabilities for host process spawning (if needed) + # Note: These may pose security risks - use with caution + # cap_add: + # - SYS_PTRACE + # security_opt: + # - apparmor:unconfined + + # Keep container running + stdin_open: true + tty: true + +volumes: + openui-state: + driver: local From 7bc913dec66a212d187cddeea510c580c5faa174 Mon Sep 17 00:00:00 2001 From: shashankanil Date: Sat, 24 Jan 2026 17:17:01 +0530 Subject: [PATCH 2/2] feat: Integrate AI agent CLIs into the full Docker image, configure hybrid mode to mount host tools, and standardize container working directories. --- Dockerfile | 32 ++++++++++++++++++------- docker-compose.full.yml | 4 +--- docker-compose.hybrid.yml | 50 ++++++++++++++++----------------------- 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/Dockerfile b/Dockerfile index 154b869..64b487e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -# Stage 1: Build frontend -FROM oven/bun:1.0.30-alpine AS builder +# Stage 1: Build frontend (Alpine is fine for building) +FROM oven/bun:1.3-alpine AS builder WORKDIR /app @@ -27,18 +27,34 @@ COPY . . WORKDIR /app/client RUN bun run build -# Stage 2: Production image -FROM oven/bun:1.0.30-alpine +# Stage 2: Production image (Debian for glibc compatibility with bun-pty) +FROM oven/bun:1.3-debian WORKDIR /app # Install runtime dependencies -RUN apk add --no-cache \ +RUN apt-get update && apt-get install -y --no-install-recommends \ bash \ git \ python3 \ - npm \ - curl + curl \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Install Node.js using NodeSource (more reliable than Debian npm) +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ + apt-get install -y nodejs && \ + rm -rf /var/lib/apt/lists/* + +# Install AI Agent CLI tools globally via npm +RUN npm install -g @anthropic-ai/claude-code opencode-ai + +# Install Ralph (autonomous Claude Code loop) +RUN git clone --depth 1 https://github.com/frankbria/ralph-claude-code.git /opt/ralph && \ + chmod +x /opt/ralph/install.sh && \ + cd /opt/ralph && ./install.sh || true && \ + ln -sf /opt/ralph/ralph /usr/local/bin/ralph && \ + ln -sf /opt/ralph/ralph-setup /usr/local/bin/ralph-setup # Copy backend dependencies COPY package.json bun.lock ./ @@ -69,4 +85,4 @@ ENV NODE_ENV=production \ OPENUI_QUIET=1 # Run the server -CMD ["bun", "run", "server/index.ts"] +CMD ["bun", "run", "/app/server/index.ts"] diff --git a/docker-compose.full.yml b/docker-compose.full.yml index f818e2a..225a279 100644 --- a/docker-compose.full.yml +++ b/docker-compose.full.yml @@ -1,5 +1,3 @@ -version: '3.9' - services: openui: build: @@ -48,7 +46,7 @@ services: - ${ANTHROPIC_API_KEY:+ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}} # Working directory inside container - working_dir: /projects + working_dir: /app # Network mode network_mode: bridge diff --git a/docker-compose.hybrid.yml b/docker-compose.hybrid.yml index 41e68db..ce624b4 100644 --- a/docker-compose.hybrid.yml +++ b/docker-compose.hybrid.yml @@ -1,9 +1,7 @@ -version: '3.9' - # HYBRID MODE - OpenUI UI in container, AI agents on host -# NOTE: This is an advanced configuration that requires additional setup. -# The sessionManager.ts needs to be modified to spawn agents via SSH, Docker CLI, or IPC. -# See README for details on implementing hybrid mode agent spawning. +# For Linux/Ubuntu systems where host networking works correctly. +# NOTE: This mode runs the UI in a container but expects AI tools (claude, opencode, ralph) +# to be installed on the HOST system, not inside the container. services: openui: @@ -13,9 +11,8 @@ services: container_name: openui-hybrid restart: unless-stopped - # Port mappings - ports: - - "6968:6968" # Backend + WebSocket + # NOTE: When using network_mode: host, the ports directive is ignored. + # The container uses the host's network directly, so port 6968 is exposed on localhost. # Volume mounts for hybrid mode volumes: @@ -25,17 +22,18 @@ services: # Plugin directory (synced with host) - ${HOME}/.openui/claude-code-plugin:/root/.openui/claude-code-plugin - # Project directories - MUST MATCH HOST PATHS - # This allows agents to run on host but UI sees same files + # Project directories - MUST MATCH HOST PATHS for agents to work correctly + # When agents spawn on the host, they need to see the same paths - ${PROJECT_DIR:-./projects}:${PROJECT_DIR:-/projects} - # Docker socket for spawning agents on host (optional, for Docker CLI method) + # Docker socket for spawning containers/commands on host - /var/run/docker.sock:/var/run/docker.sock - # Host binary access (if AI tools are installed in these locations) - # Uncomment and adjust paths based on your host setup: - # - /usr/local/bin/claude:/usr/local/bin/claude:ro - # - /usr/local/bin/opencode:/usr/local/bin/opencode:ro + # Mount host AI tools into container (required for hybrid mode) + # These paths may vary based on your installation method + - /usr/local/bin/claude:/usr/local/bin/host-claude:ro + - /usr/local/bin/opencode:/usr/local/bin/host-opencode:ro + - /usr/local/bin/ralph:/usr/local/bin/host-ralph:ro # Git credentials - ${HOME}/.gitconfig:/root/.gitconfig:ro @@ -48,27 +46,19 @@ services: - LAUNCH_CWD=${PROJECT_DIR:-/projects} - OPENUI_QUIET=1 - # Hybrid mode flag (for future use in sessionManager) + # Hybrid mode flag - OPENUI_HYBRID_MODE=true - # Path to host tools (accessed via mount) - adjust as needed - # - CLAUDE_BIN_PATH=/usr/local/bin/claude - # - OPENCODE_BIN_PATH=/usr/local/bin/opencode + # Anthropic API key (required for Claude Code) + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} - # Working directory - working_dir: ${PROJECT_DIR:-/projects} + # Working directory (must be /app for static file serving) + working_dir: /app - # Network mode - use host to access host services - # Alternatively, use 'bridge' and configure SSH to host + # Network mode: host gives full access to host network + # This works properly on Linux but NOT on macOS/Windows Docker Desktop network_mode: host - # Extra capabilities for host process spawning (if needed) - # Note: These may pose security risks - use with caution - # cap_add: - # - SYS_PTRACE - # security_opt: - # - apparmor:unconfined - # Keep container running stdin_open: true tty: true