From eef817ff8e20047e993f0ced1c8c90a01a445e2d Mon Sep 17 00:00:00 2001 From: casistack Date: Thu, 9 Jan 2025 19:46:43 +0000 Subject: [PATCH] Add docker support --- .env.example | 14 +++++- Dockerfile | 82 ++++++++++++++++++++++++++++++ README.md | 95 +++++++++++++++++++++++++++++++++-- docker-compose.yml | 51 +++++++++++++++++++ src/browser/config.py | 30 +++++++++++ src/browser/custom_browser.py | 7 +++ src/browser/custom_context.py | 2 + supervisord.conf | 83 ++++++++++++++++++++++++++++++ 8 files changed, 360 insertions(+), 4 deletions(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 src/browser/config.py create mode 100644 supervisord.conf diff --git a/.env.example b/.env.example index e13240b..2ebe67b 100644 --- a/.env.example +++ b/.env.example @@ -17,5 +17,17 @@ ANONYMIZED_TELEMETRY=true # LogLevel: Set to debug to enable verbose logging, set to result to get results only. Available: result | debug | info BROWSER_USE_LOGGING_LEVEL=info +# Chrome settings CHROME_PATH= -CHROME_USER_DATA= \ No newline at end of file +CHROME_USER_DATA= +CHROME_DEBUGGING_PORT=9222 +CHROME_DEBUGGING_HOST=localhost +CHROME_PERSISTENT_SESSION=false # Set to true to keep browser open between AI tasks + +# Display settings +RESOLUTION=1920x1080x24 # Format: WIDTHxHEIGHTxDEPTH +RESOLUTION_WIDTH=1920 # Width in pixels +RESOLUTION_HEIGHT=1080 # Height in pixels + +# VNC settings +VNC_PASSWORD=youvncpassword \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..af1d438 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,82 @@ +FROM python:3.11-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + wget \ + gnupg \ + curl \ + unzip \ + xvfb \ + libgconf-2-4 \ + libxss1 \ + libnss3 \ + libnspr4 \ + libasound2 \ + libatk1.0-0 \ + libatk-bridge2.0-0 \ + libcups2 \ + libdbus-1-3 \ + libdrm2 \ + libgbm1 \ + libgtk-3-0 \ + libxcomposite1 \ + libxdamage1 \ + libxfixes3 \ + libxrandr2 \ + xdg-utils \ + fonts-liberation \ + dbus \ + xauth \ + xvfb \ + x11vnc \ + tigervnc-tools \ + supervisor \ + net-tools \ + procps \ + git \ + python3-numpy \ + && rm -rf /var/lib/apt/lists/* + +# Install noVNC +RUN git clone https://github.com/novnc/noVNC.git /opt/novnc \ + && git clone https://github.com/novnc/websockify /opt/novnc/utils/websockify \ + && ln -s /opt/novnc/vnc.html /opt/novnc/index.html + +# Install Chrome +RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ + && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list \ + && apt-get update \ + && apt-get install -y google-chrome-stable \ + && rm -rf /var/lib/apt/lists/* + +# Set up working directory +WORKDIR /app + +# Copy requirements and install Python dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Install Playwright and browsers with system dependencies +ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright +RUN playwright install --with-deps chromium +RUN playwright install-deps + +# Copy the application code +COPY . . + +# Set environment variables +ENV PYTHONUNBUFFERED=1 +ENV BROWSER_USE_LOGGING_LEVEL=info +ENV CHROME_PATH=/usr/bin/google-chrome +ENV ANONYMIZED_TELEMETRY=false +ENV DISPLAY=:99 +ENV RESOLUTION=1920x1080x24 +ENV VNC_PASSWORD=vncpassword + +# Set up supervisor configuration +RUN mkdir -p /var/log/supervisor +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf + +EXPOSE 7788 6080 5900 + +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] \ No newline at end of file diff --git a/README.md b/README.md index 1ebee46..bd6d123 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,45 @@ We would like to officially thank [WarmShao](https://github.com/warmshao) for hi **Custom Browser Support:** You can use your own browser with our tool, eliminating the need to re-login to sites or deal with other authentication challenges. This feature also supports high-definition screen recording. - +**Persistent Browser Sessions:** You can choose to keep the browser window open between AI tasks, allowing you to see the complete history and state of AI interactions. -## Installation Guide + + +## Installation Options + +### Option 1: Docker Installation (Recommended) + +1. **Prerequisites:** + - Docker and Docker Compose installed on your system + - Git to clone the repository + +2. **Setup:** + ```bash + # Clone the repository + git clone + cd browser-use-webui + + # Copy and configure environment variables + cp .env.example .env + # Edit .env with your preferred text editor and add your API keys + ``` + +3. **Run with Docker:** + ```bash + # Build and start the container with default settings (browser closes after AI tasks) + docker compose up --build + + # Or run with persistent browser (browser stays open between AI tasks) + CHROME_PERSISTENT_SESSION=true docker compose up --build + ``` + +4. **Access the Application:** + - WebUI: `http://localhost:7788` + - VNC Viewer (to see browser interactions): `http://localhost:6080/vnc.html` + + Default VNC password is "vncpassword". You can change it by setting the `VNC_PASSWORD` environment variable in your `.env` file. + +### Option 2: Local Installation Read the [quickstart guide](https://docs.browser-use.com/quickstart#prepare-the-environment) or follow the steps below to get started. @@ -51,6 +87,59 @@ playwright install ## Usage +### Docker Setup +1. **Environment Variables:** + - All configuration is done through the `.env` file + - Available environment variables: + ``` + # LLM API Keys + OPENAI_API_KEY=your_key_here + ANTHROPIC_API_KEY=your_key_here + GOOGLE_API_KEY=your_key_here + + # Browser Settings + CHROME_PERSISTENT_SESSION=true # Set to true to keep browser open between AI tasks + RESOLUTION=1920x1080x24 # Custom resolution format: WIDTHxHEIGHTxDEPTH + RESOLUTION_WIDTH=1920 # Custom width in pixels + RESOLUTION_HEIGHT=1080 # Custom height in pixels + + # VNC Settings + VNC_PASSWORD=your_vnc_password # Optional, defaults to "vncpassword" + ``` + +2. **Browser Persistence Modes:** + - **Default Mode (CHROME_PERSISTENT_SESSION=false):** + - Browser opens and closes with each AI task + - Clean state for each interaction + - Lower resource usage + + - **Persistent Mode (CHROME_PERSISTENT_SESSION=true):** + - Browser stays open between AI tasks + - Maintains history and state + - Allows viewing previous AI interactions + - Set in `.env` file or via environment variable when starting container + +3. **Viewing Browser Interactions:** + - Access the noVNC viewer at `http://localhost:6080/vnc.html` + - Enter the VNC password (default: "vncpassword" or what you set in VNC_PASSWORD) + - You can now see all browser interactions in real-time + +4. **Container Management:** + ```bash + # Start with persistent browser + CHROME_PERSISTENT_SESSION=true docker compose up -d + + # Start with default mode (browser closes after tasks) + docker compose up -d + + # View logs + docker compose logs -f + + # Stop the container + docker compose down + ``` + +### Local Setup 1. **Run the WebUI:** ```bash python webui.py --ip 127.0.0.1 --port 7788 @@ -129,4 +218,4 @@ CHROME_USER_DATA="~/Library/Application Support/Google/Chrome/Profile 1" ## Changelog -- [x] **2025/01/06:** Thanks to @richard-devbot, a New and Well-Designed WebUI is released. [Video tutorial demo](https://github.com/warmshao/browser-use-webui/issues/1#issuecomment-2573393113). +- [x] **2025/01/06:** Thanks to @richard-devbot, a New and Well-Designed WebUI is released. [Video tutorial demo](https://github.com/warmshao/browser-use-webui/issues/1#issuecomment-2573393113). \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6253a4a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,51 @@ +services: + browser-use-webui: + build: + context: . + dockerfile: Dockerfile + ports: + - "7788:7788" # Gradio default port + - "6080:6080" # noVNC web interface + - "5900:5900" # VNC port + - "9222:9222" # Chrome remote debugging port + environment: + - OPENAI_ENDPOINT=${OPENAI_ENDPOINT:-https://api.openai.com/v1} + - OPENAI_API_KEY=${OPENAI_API_KEY:-} + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} + - GOOGLE_API_KEY=${GOOGLE_API_KEY:-} + - AZURE_OPENAI_ENDPOINT=${AZURE_OPENAI_ENDPOINT:-} + - AZURE_OPENAI_API_KEY=${AZURE_OPENAI_API_KEY:-} + - DEEPSEEK_ENDPOINT=${DEEPSEEK_ENDPOINT:-https://api.deepseek.com} + - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-} + - BROWSER_USE_LOGGING_LEVEL=${BROWSER_USE_LOGGING_LEVEL:-info} + - ANONYMIZED_TELEMETRY=false + - CHROME_PATH=/usr/bin/google-chrome + - CHROME_USER_DATA=/app/data/chrome_data + - CHROME_PERSISTENT_SESSION=${CHROME_PERSISTENT_SESSION:-false} + - DISPLAY=:99 + - PLAYWRIGHT_BROWSERS_PATH=/ms-playwright + - RESOLUTION=${RESOLUTION:-1920x1080x24} + - RESOLUTION_WIDTH=${RESOLUTION_WIDTH:-1920} + - RESOLUTION_HEIGHT=${RESOLUTION_HEIGHT:-1080} + - VNC_PASSWORD=${VNC_PASSWORD:-vncpassword} + - PERSISTENT_BROWSER_PORT=9222 + - PERSISTENT_BROWSER_HOST=localhost + - CHROME_DEBUGGING_PORT=9222 + - CHROME_DEBUGGING_HOST=localhost + volumes: + - ./data:/app/data + - ./data/chrome_data:/app/data/chrome_data + - /tmp/.X11-unix:/tmp/.X11-unix + restart: unless-stopped + shm_size: '2gb' + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + tmpfs: + - /tmp + healthcheck: + test: ["CMD", "nc", "-z", "localhost", "5900"] + interval: 10s + timeout: 5s + retries: 3 \ No newline at end of file diff --git a/src/browser/config.py b/src/browser/config.py new file mode 100644 index 0000000..32329c4 --- /dev/null +++ b/src/browser/config.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# @Time : 2025/1/6 +# @Author : wenshao +# @ProjectName: browser-use-webui +# @FileName: config.py + +import os +from dataclasses import dataclass +from typing import Optional + + +@dataclass +class BrowserPersistenceConfig: + """Configuration for browser persistence""" + + persistent_session: bool = False + user_data_dir: Optional[str] = None + debugging_port: Optional[int] = None + debugging_host: Optional[str] = None + + @classmethod + def from_env(cls) -> "BrowserPersistenceConfig": + """Create config from environment variables""" + return cls( + persistent_session=os.getenv("CHROME_PERSISTENT_SESSION", "").lower() + == "true", + user_data_dir=os.getenv("CHROME_USER_DATA"), + debugging_port=int(os.getenv("CHROME_DEBUGGING_PORT", "9222")), + debugging_host=os.getenv("CHROME_DEBUGGING_HOST", "localhost"), + ) \ No newline at end of file diff --git a/src/browser/custom_browser.py b/src/browser/custom_browser.py index 790eb95..c8669af 100644 --- a/src/browser/custom_browser.py +++ b/src/browser/custom_browser.py @@ -7,6 +7,7 @@ from browser_use.browser.browser import Browser from browser_use.browser.context import BrowserContext, BrowserContextConfig +from .config import BrowserPersistenceConfig from .custom_context import CustomBrowserContext @@ -18,3 +19,9 @@ class CustomBrowser(Browser): ) -> BrowserContext: """Create a browser context""" return CustomBrowserContext(config=config, browser=self, context=context) + async def close(self): + """Override close to respect persistence setting""" + # Check if persistence is enabled before closing + persistence_config = BrowserPersistenceConfig.from_env() + if not persistence_config.persistent_session: + await super().close() diff --git a/src/browser/custom_context.py b/src/browser/custom_context.py index 03ac869..db53973 100644 --- a/src/browser/custom_context.py +++ b/src/browser/custom_context.py @@ -13,6 +13,7 @@ from browser_use.browser.browser import Browser from browser_use.browser.context import BrowserContext, BrowserContextConfig from playwright.async_api import Browser as PlaywrightBrowser +from .config import BrowserPersistenceConfig logger = logging.getLogger(__name__) @@ -25,6 +26,7 @@ class CustomBrowserContext(BrowserContext): ): super(CustomBrowserContext, self).__init__(browser=browser, config=config) self.context = context + async def _create_context(self, browser: PlaywrightBrowser): """Creates a new browser context with anti-detection measures and loads cookies if available.""" diff --git a/supervisord.conf b/supervisord.conf new file mode 100644 index 0000000..ff884c8 --- /dev/null +++ b/supervisord.conf @@ -0,0 +1,83 @@ +[supervisord] +nodaemon=true +logfile=/dev/stdout +logfile_maxbytes=0 +loglevel=debug + +[program:xvfb] +command=Xvfb :99 -screen 0 %(ENV_RESOLUTION)s -ac +extension GLX +render -noreset +autorestart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +priority=100 +startsecs=3 + +[program:vnc_setup] +command=bash -c "mkdir -p ~/.vnc && echo '%(ENV_VNC_PASSWORD)s' | vncpasswd -f > ~/.vnc/passwd && chmod 600 ~/.vnc/passwd && ls -la ~/.vnc/passwd" +autorestart=false +startsecs=0 +priority=150 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:x11vnc] +command=bash -c "sleep 3 && DISPLAY=:99 x11vnc -display :99 -forever -shared -rfbauth /root/.vnc/passwd -rfbport 5900 -bg -o /var/log/x11vnc.log" +autorestart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +priority=200 +startretries=5 +startsecs=5 +depends_on=vnc_setup + +[program:x11vnc_log] +command=tail -f /var/log/x11vnc.log +autorestart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +priority=250 + +[program:novnc] +command=bash -c "sleep 5 && cd /opt/novnc && ./utils/novnc_proxy --vnc localhost:5900 --listen 0.0.0.0:6080 --web /opt/novnc" +autorestart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +priority=300 +startretries=5 +startsecs=3 +depends_on=x11vnc + +[program:persistent_browser] +command=bash -c 'if [ "%(ENV_CHROME_PERSISTENT_SESSION)s" = "true" ]; then mkdir -p /app/data/chrome_data && sleep 8 && google-chrome --user-data-dir=/app/data/chrome_data --window-position=0,0 --window-size=%(ENV_RESOLUTION_WIDTH)s,%(ENV_RESOLUTION_HEIGHT)s --start-maximized --no-sandbox --disable-dev-shm-usage --disable-gpu --disable-software-rasterizer --disable-setuid-sandbox --no-first-run --no-default-browser-check --no-experiments --ignore-certificate-errors --remote-debugging-port=9222 --remote-debugging-address=0.0.0.0 "data:text/html,

Browser Ready for AI Interaction

"; else echo "Persistent browser disabled"; fi' +autorestart=%(ENV_CHROME_PERSISTENT_SESSION)s +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +priority=350 +startretries=3 +startsecs=3 +depends_on=novnc + +[program:webui] +command=python webui.py --ip 0.0.0.0 --port 7788 +directory=/app +autorestart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +priority=400 +startretries=3 +startsecs=3 +depends_on=persistent_browser \ No newline at end of file