Get Started →

    On this page

    How to Install OpenClaw with Docker (The 5-Minute Containerized Setup)

    Meta Description: Install OpenClaw with Docker in 5 minutes. Drop-in docker-compose.yml, env file structure, volume mounts for memory persistence, and WhatsApp/Telegram socket mapping explained.

    Docker turns “works on my machine” into “works everywhere.” One command, your AI agent is running. No dependency hell. No version conflicts. No “but it worked yesterday.”

    OpenClaw in Docker means you can spin up an instance in 5 minutes, tear it down just as fast, and move it between servers without reconfiguring anything.

    This guide covers the drop-in docker-compose setup, environment file structure, volume mounts for memory persistence, and the gotcha around mapping WhatsApp/Telegram sockets that trips up first-timers.

    By the end, you’ll have OpenClaw running in a container with persistent memory and messaging integrations working.

    Why Docker for OpenClaw

    The traditional install:

    • Install Node.js (specific version)
    • Install dependencies (hope nothing breaks)
    • Configure environment
    • Set up system services
    • Debug path issues
    • Repeat on every server

    The Docker install:

    • Pull image
    • Run container
    • Done

    Benefits:

    Isolation: OpenClaw and dependencies contained. Won’t conflict with other apps on your server.

    Portability: Same container runs on your laptop, VPS, or cloud. No environment differences.

    Reproducibility: Everyone gets identical setup. No “works for me” bugs.

    Rollback: Bad update? Revert to previous image instantly.

    Scaling: Need 5 instances? Copy the docker-compose, change ports, run.

    The tradeoff: Slightly more disk space (image overhead) and marginal performance cost (containerization). For most users, worth it.

    Prerequisites

    Install Docker:

    Ubuntu/Debian:

    curl -fsSL https://get.docker.com -o get-docker.sh
    sudo sh get-docker.sh
    sudo usermod -aG docker $USER
    newgrp docker
    

    macOS: Download Docker Desktop from docker.com

    Windows: Download Docker Desktop from docker.com (requires WSL2)

    Verify:

    docker --version
    docker-compose --version
    

    Should show Docker 20+ and Docker Compose 2+.

    The 5-Minute Setup

    Step 1: Create Project Directory

    mkdir openclaw-docker
    cd openclaw-docker
    

    Step 2: Create docker-compose.yml

    Create docker-compose.yml:

    version: '3.8'
    
    services:
      openclaw:
        image: openclaw/openclaw:latest
        container_name: openclaw
        restart: unless-stopped
        
        env_file:
          - .env
        
        volumes:
          # Memory persistence
          - ./data:/app/data
          
          # Configuration
          - ./config:/app/config
          
          # Logs
          - ./logs:/app/logs
          
          # WhatsApp socket (important!)
          - ./whatsapp:/app/.wwebjs_auth
          
          # Telegram session
          - ./telegram:/app/telegram-sessions
        
        ports:
          - "3000:3000"
        
        # Optional: expose web UI
        # - "8080:8080"
        
        networks:
          - openclaw-net
    
    networks:
      openclaw-net:
        driver: bridge
    

    What this does:

    • image: Pulls official OpenClaw Docker image
    • restart: Auto-restart if container crashes
    • env_file: Loads environment variables from .env
    • volumes: Maps local directories to container (data persists)
    • ports: Exposes OpenClaw API (and optionally web UI)

    Step 3: Create .env File

    Create .env:

    # Core Configuration
    NODE_ENV=production
    OPENCLAW_API_KEY=your-secret-api-key-here
    
    # Telegram
    TELEGRAM_ENABLED=true
    TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
    TELEGRAM_PHONE_NUMBER=+15551234567
    
    # WhatsApp
    WHATSAPP_ENABLED=true
    WHATSAPP_SESSION_NAME=openclaw-session
    
    # Discord
    DISCORD_ENABLED=false
    DISCORD_BOT_TOKEN=your-discord-bot-token
    
    # Slack
    SLACK_ENABLED=false
    SLACK_BOT_TOKEN=xoxb-your-slack-token
    SLACK_APP_TOKEN=xapp-your-app-token
    
    # Google Calendar
    GOOGLE_CALENDAR_ENABLED=false
    GOOGLE_CLIENT_ID=your-google-client-id
    GOOGLE_CLIENT_SECRET=your-google-secret
    
    # Memory Backend
    MEMORY_BACKEND=sqlite
    MEMORY_DB_PATH=/app/data/memory.db
    
    # Logging
    LOG_LEVEL=info
    LOG_FILE=/app/logs/openclaw.log
    

    Security note: Add .env to .gitignore. Never commit tokens.

    Step 4: Create Directory Structure

    mkdir -p data config logs whatsapp telegram
    

    Step 5: Start OpenClaw

    docker-compose up -d
    

    What happens:

    1. Docker pulls openclaw/openclaw:latest image (if not cached)
    2. Creates container from image
    3. Mounts volumes
    4. Loads .env
    5. Starts OpenClaw in background (-d flag)

    Check status:

    docker-compose ps
    

    Should show:

    NAME                COMMAND             STATUS              PORTS
    openclaw            "node index.js"     Up 10 seconds       0.0.0.0:3000->3000/tcp
    

    View logs:

    docker-compose logs -f
    

    You should see:

    [INFO] OpenClaw starting...
    [INFO] Telegram bot connected
    [INFO] WhatsApp initializing...
    [INFO] Agent ready
    

    Volume Mounts Explained

    Why volumes matter: Containers are ephemeral. When container stops, data inside vanishes. Volumes persist data on host machine.

    Critical Volumes

    ./data → /app/data

    • Memory database (conversations, user context)
    • Agent state
    • Cached data

    Without this: Every restart = fresh agent with no memory.

    ./config → /app/config

    • Custom skills
    • Agent configuration
    • Workflow definitions

    ./whatsapp → /app/.wwebjs_auth

    • WhatsApp session data
    • QR code auth persistence
    • Message encryption keys

    Without this: Re-scan QR code every restart.

    ./telegram → /app/telegram-sessions

    • Telegram session files
    • Auth tokens

    Without this: Re-authenticate every restart.

    View Volume Data

    ls -la data/
    # Shows memory.db, cache files
    
    ls -la whatsapp/
    # Shows WhatsApp session
    

    The WhatsApp/Telegram Socket Gotcha

    The problem: WhatsApp uses a persistent WebSocket connection. When container restarts, connection breaks. Session must be remounted.

    WhatsApp Volume Mapping

    Correct:

    volumes:
      - ./whatsapp:/app/.wwebjs_auth
    

    Maps the ENTIRE .wwebjs_auth directory, not just session file.

    Why this matters: WhatsApp stores:

    • Session credentials
    • Message keys
    • Media cache
    • Browser session data

    If volume is missing: You’ll re-scan QR code on every restart.

    First-Time WhatsApp Setup

    Start container:

    docker-compose up
    

    Watch logs:

    docker-compose logs -f openclaw
    

    You’ll see:

    [WhatsApp] QR Code:
    ████ ▄▄▄▄▄ █▀█ █▄▄▀▄▀▀ ▄▄▄▄▄ ████
    ████ █   █ █▀▀▀█ ▀ ▀█ █   █ ████
    ████ █▄▄▄█ █▀ █▀▀ ▄ █ █▄▄▄█ ████
    ...
    

    Scan with WhatsApp mobile app:

    1. Open WhatsApp on phone
    2. Settings → Linked Devices → Link a Device
    3. Scan QR code from terminal

    Once connected:

    [WhatsApp] Client is ready!
    

    Session is now saved in ./whatsapp/ volume.

    Test persistence:

    docker-compose restart
    

    Should NOT show QR code again. If it does, volume isn’t mounted correctly.

    Telegram Session Persistence

    Similar issue with Telegram. Session files must persist.

    Correct volume:

    - ./telegram:/app/telegram-sessions
    

    First-time auth:

    [Telegram] Enter phone number: +15551234567
    [Telegram] Enter code from Telegram: 12345
    

    After auth, session saved to ./telegram/ volume.

    Subsequent restarts: No re-auth needed.

    Environment File Structure

    The .env file controls everything. Understanding its structure helps you customize.

    Section 1: Core Settings

    NODE_ENV=production
    OPENCLAW_API_KEY=your-secret-key
    

    NODE_ENV: development or production

    • Production: Optimized, less logging
    • Development: More logs, hot reload

    OPENCLAW_API_KEY: Used if you expose API endpoints. Generate random string:

    openssl rand -base64 32
    

    Section 2: Messaging Channels

    Each channel has _ENABLED flag:

    TELEGRAM_ENABLED=true
    WHATSAPP_ENABLED=true
    DISCORD_ENABLED=false
    

    Set to false to disable without removing credentials.

    Section 3: Memory Backend

    MEMORY_BACKEND=sqlite
    MEMORY_DB_PATH=/app/data/memory.db
    

    Options:

    • sqlite: File-based (default, simple)
    • postgres: External database (production)
    • redis: In-memory (fast, requires Redis)

    For Docker, SQLite is fine unless you need multi-container setup.

    Section 4: Logging

    LOG_LEVEL=info
    LOG_FILE=/app/logs/openclaw.log
    

    LOG_LEVEL options:

    • error: Only errors
    • warn: Warnings and errors
    • info: Normal operation (recommended)
    • debug: Verbose (for troubleshooting)

    Hot Reloading Environment

    Change .env:

    nano .env
    # Edit values
    

    Restart container:

    docker-compose restart
    

    Changes apply immediately (no rebuild needed).

    Building Custom Image

    Want to add custom skills or modify OpenClaw?

    Create Dockerfile

    Create Dockerfile:

    FROM openclaw/openclaw:latest
    
    # Copy custom skills
    COPY ./custom-skills /app/skills/custom
    
    # Copy custom config
    COPY ./my-config.yml /app/config/agent.yml
    
    # Install additional dependencies (if needed)
    RUN npm install some-extra-package
    
    # Expose any additional ports
    EXPOSE 9000
    
    CMD ["node", "index.js"]
    

    Build Image

    docker build -t openclaw-custom:v1 .
    

    Update docker-compose.yml

    services:
      openclaw:
        image: openclaw-custom:v1  # Use your custom image
        build:
          context: .
          dockerfile: Dockerfile
    

    Rebuild and Run

    docker-compose up --build -d
    

    Multi-Container Setup

    Run multiple OpenClaw instances for different users/use cases.

    Create docker-compose-multi.yml

    version: '3.8'
    
    services:
      openclaw-personal:
        image: openclaw/openclaw:latest
        container_name: openclaw-personal
        env_file:
          - .env.personal
        volumes:
          - ./data-personal:/app/data
          - ./whatsapp-personal:/app/.wwebjs_auth
        ports:
          - "3001:3000"
        networks:
          - openclaw-net
    
      openclaw-work:
        image: openclaw/openclaw:latest
        container_name: openclaw-work
        env_file:
          - .env.work
        volumes:
          - ./data-work:/app/data
          - ./whatsapp-work:/app/.wwebjs_auth
        ports:
          - "3002:3000"
        networks:
          - openclaw-net
    
    networks:
      openclaw-net:
        driver: bridge
    

    Run both:

    docker-compose -f docker-compose-multi.yml up -d
    

    Result: Two isolated OpenClaw instances, different configs, different messaging accounts.

    Backup and Restore

    Backup

    Stop container:

    docker-compose down
    

    Backup volumes:

    tar -czf openclaw-backup-$(date +%Y%m%d).tar.gz data/ whatsapp/ telegram/ config/ .env
    

    Restart:

    docker-compose up -d
    

    Restore

    Extract backup:

    tar -xzf openclaw-backup-20260508.tar.gz
    

    Start container:

    docker-compose up -d
    

    All data restored (memory, sessions, config).

    Updating OpenClaw

    Pull Latest Image

    docker-compose pull
    

    Restart with New Image

    docker-compose up -d
    

    Docker pulls new version, restarts container. Your data (in volumes) is preserved.

    Rollback if Needed

    Check image history:

    docker images openclaw/openclaw
    

    Run specific version:

    services:
      openclaw:
        image: openclaw/openclaw:v1.2.3  # Specific version
    
    docker-compose up -d
    

    Health Checks

    Add health check to docker-compose.yml:

    services:
      openclaw:
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
          interval: 30s
          timeout: 10s
          retries: 3
          start_period: 40s
    

    Check health:

    docker inspect --format='{{.State.Health.Status}}' openclaw
    

    Should return: healthy

    Common Docker Issues

    “Port already in use”

    Error:

    Error starting userland proxy: listen tcp 0.0.0.0:3000: bind: address already in use
    

    Cause: Another process using port 3000.

    Fix 1 – Change port:

    ports:
      - "3001:3000"  # Host port 3001 instead
    

    Fix 2 – Kill process:

    sudo lsof -ti:3000 | xargs kill
    

    “Volume mount permission denied”

    Error:

    permission denied while trying to connect to the Docker daemon socket
    

    Cause: User not in docker group.

    Fix:

    sudo usermod -aG docker $USER
    newgrp docker
    

    “Container keeps restarting”

    Check logs:

    docker-compose logs openclaw
    

    Common causes:

    • Missing required env vars (.env incomplete)
    • Bad credentials (Telegram token expired)
    • Port conflict

    “WhatsApp QR code on every restart”

    Cause: Volume not mounted or wrong path.

    Fix: Verify volume in docker-compose.yml:

    volumes:
      - ./whatsapp:/app/.wwebjs_auth  # Must match OpenClaw's path
    

    Check directory exists:

    ls -la whatsapp/
    

    Should show session files after first QR scan.

    Resource Limits

    Prevent OpenClaw from consuming all system resources.

    Add Resource Constraints

    services:
      openclaw:
        deploy:
          resources:
            limits:
              cpus: '1.0'      # Max 1 CPU core
              memory: 1024M    # Max 1GB RAM
            reservations:
              cpus: '0.5'      # Reserve 0.5 core
              memory: 512M     # Reserve 512MB
    

    Monitor usage:

    docker stats openclaw
    

    Shows real-time CPU, memory, network, disk usage.

    Docker Compose Profiles

    Run different configurations without multiple compose files.

    Add Profiles

    services:
      openclaw:
        profiles: ["production"]
        image: openclaw/openclaw:latest
        # ... rest of config
    
      openclaw-dev:
        profiles: ["development"]
        image: openclaw/openclaw:dev
        volumes:
          - ./src:/app/src  # Mount source for hot reload
        environment:
          - NODE_ENV=development
    

    Run production:

    docker-compose --profile production up -d
    

    Run development:

    docker-compose --profile development up -d
    

    The PaioClaw Pre-Built Image Alternative

    Setup time so far: 5-10 minutes (Docker install, compose file, first QR scan).

    What you’ve handled:

    • Docker installation
    • docker-compose.yml creation
    • .env configuration
    • Volume mapping for persistence
    • WhatsApp/Telegram socket gotcha
    • First-time authentication

    Ongoing maintenance:

    • Image updates (pull, restart)
    • Volume backups
    • Resource monitoring
    • Log rotation

    PaioClaw pre-built image:

    Docker image included, but fully managed:

    1. Pre-configured docker-compose
    2. Automatic volume setup
    3. One-click messaging auth
    4. Managed updates
    5. Built-in monitoring

    Total time: 2 minutes (paste API key, scan QR).

    Includes:

    • Pre-optimized image (smaller, faster)
    • Automatic backup to cloud storage
    • Resource optimization (CPU/memory tuning)
    • Health monitoring and auto-restart
    • Log aggregation

    Cost: Starts FREE, Smart $15/month, Genius $25/month.

    When to DIY Docker:

    • You need full container control
    • Custom image modifications
    • Multi-instance orchestration
    • Learning Docker/containers

    When to use PaioClaw:

    • You want Docker benefits without Docker expertise
    • Automatic backups and monitoring
    • Managed updates
    • Support when things break

    The honest truth: Docker setup is straightforward if you know Docker. If docker-compose.yml looks like hieroglyphics, PaioClaw handles the complexity.

    The Bottom Line

    Docker makes OpenClaw portable, reproducible, and isolated. The setup is genuinely 5 minutes once you understand volume mounts and the WhatsApp/Telegram socket gotcha.

    Critical takeaways:

    • Volume mounts preserve data across restarts
    • WhatsApp/Telegram sessions MUST be in volumes
    • .env file controls all configuration
    • docker-compose makes management simple

    If you followed this guide, you now have OpenClaw running in Docker with persistent memory and working messaging integrations.

    Whether you manage your own Docker setup or use PaioClaw’s pre-built image depends on whether you want infrastructure control or infrastructure convenience.

    Want Docker without the YAML? PaioClaw’s managed Docker deployment handles compose files, volume mounts, backups, and monitoring automatically. One-click setup, zero Docker knowledge required. Starts FREE, Smart $15/month, Genius $25/month. Start free →

    Join Our Community

    Connect with other PaioClaw users, share tips, and stay up to date.