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.