Setup & Deployment

How to Run OpenClaw in Docker: The Complete Setup Guide (2026)

16 min read · Updated 2026-03-04

By DoneClaw Team · We run managed OpenClaw deployments and write from hands-on production experience.

Running OpenClaw in Docker gives you a fully isolated, reproducible AI agent environment that you can spin up in minutes, tear down without a trace, and deploy identically across any machine. Whether you're trying OpenClaw for the first time on your laptop, deploying it to a VPS, or building a production setup with agent sandboxing — Docker is the cleanest path. This guide covers everything: from the one-command quick start to advanced multi-container architectures with Ollama, sandbox isolation, automated updates, and the troubleshooting fixes that will save you hours of debugging.

Why Run OpenClaw in Docker?

Before diving into commands, let's be clear about when Docker makes sense — and when it doesn't.

Docker Is Right for You If:

Skip Docker If:

  • **You want isolation.** OpenClaw runs code, browses the web, and executes shell commands. Docker contains all of that inside a boundary you control.
  • **You're deploying to a VPS.** Docker standardizes the environment so your Hetzner box, DigitalOcean droplet, or AWS instance all run the same image.
  • **You want reproducibility.** Pin an image tag, and you'll get the exact same OpenClaw version months later.
  • **You run multiple services.** Docker Compose makes it trivial to run OpenClaw alongside Ollama, Traefik, monitoring tools, or databases.
  • **You value clean uninstalls.** Remove the containers and volumes, and OpenClaw is gone. No leftover global packages.
  • You're developing on your own machine and want the fastest iteration loop — the native install is simpler.
  • You're on a Raspberry Pi with limited RAM (under 2 GB) — the Docker build itself may OOM. See our Raspberry Pi guide for the direct install approach.

Prerequisites

Before starting, make sure you have:

Requirement: Docker Engine / Desktop, Minimum: v24+, Recommended: v27+

Requirement: Docker Compose, Minimum: v2.20+, Recommended: v2.30+

Requirement: RAM (for build), Minimum: 2 GB, Recommended: 4 GB

Requirement: RAM (for runtime), Minimum: 1 GB, Recommended: 2 GB

Requirement: Disk space, Minimum: 3 GB, Recommended: 5 GB

Requirement: OS, Minimum: Linux, macOS, Windows (WSL2), Recommended: Ubuntu 22.04+

Check your versions:

If you're on a VPS, make sure you're not running as a non-Docker user. You'll need `docker` group membership or root access:

docker --version
docker compose version
sudo usermod -aG docker $USER
# Log out and back in for this to take effect

Quick Start: One Command Setup

OpenClaw's Docker setup is designed around a single script that handles everything:

That's it. The script will:

1. **Build the Docker image** locally from the Dockerfile (or pull a remote image if configured) 2. **Run the onboarding wizard** — asks about model provider, messaging channels, and configuration 3. **Generate a gateway token** and write it to `.env` 4. **Start the gateway** via Docker Compose 5. **Print the dashboard URL** so you can access the web UI

After completion, open `http://127.0.0.1:18789/` in your browser and paste the generated token into Settings.

What Gets Created on Your Host

The setup creates two directories that persist outside Docker:

These are bind-mounted into the container, so your data survives container restarts and rebuilds.

git clone https://github.com/openclaw/openclaw.git
cd openclaw
./docker-setup.sh
~/.openclaw/           # Configuration, API keys, agent memory
~/.openclaw/workspace/ # Agent workspace — files the agent creates live here

Understanding the Docker Compose Architecture

OpenClaw's `docker-compose.yml` defines two services:

1. `openclaw-gateway` — The Main Service

This is the OpenClaw brain. It runs the gateway server, handles messaging channels (Telegram, Discord, WhatsApp), manages agent sessions, and exposes the web dashboard.

Key details:

2. `openclaw-cli` — The Management Tool

This is a helper container for running CLI commands against the gateway:

Notice the security hardening: `cap_drop` removes network capabilities, and `no-new-privileges` prevents privilege escalation. The `network_mode: "service:openclaw-gateway"` shares the gateway's network namespace so the CLI can reach `127.0.0.1:18789`.

Use it like this:

  • **Port 18789**: Web dashboard and API
  • **Port 18790**: Bridge port for node pairing (phone, other devices)
  • **`init: true`**: Ensures proper signal handling and zombie process cleanup
  • **`restart: unless-stopped`**: Auto-restart on crashes, but not after manual `docker compose stop`
  • **Health check**: Polls `/healthz` every 30 seconds — integrates with Docker's health monitoring
services:
  openclaw-gateway:
    image: ${OPENCLAW_IMAGE:-openclaw:local}
    environment:
      HOME: /home/node
      TERM: xterm-256color
      OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN}
    volumes:
      - ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
      - ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
    ports:
      - "${OPENCLAW_GATEWAY_PORT:-18789}:18789"
      - "${OPENCLAW_BRIDGE_PORT:-18790}:18790"
    init: true
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "node", "-e",
        "fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 20s
  openclaw-cli:
    image: ${OPENCLAW_IMAGE:-openclaw:local}
    network_mode: "service:openclaw-gateway"
    cap_drop:
      - NET_RAW
      - NET_ADMIN
    security_opt:
      - no-new-privileges:true
    volumes:
      - ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
      - ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
    stdin_open: true
    tty: true
    init: true
    entrypoint: ["node", "dist/index.js"]
    depends_on:
      - openclaw-gateway
# Check gateway status
docker compose run --rm openclaw-cli gateway probe

# List connected devices
docker compose run --rm openclaw-cli devices list

# Approve a pairing request
docker compose run --rm openclaw-cli pairing approve telegram <CODE>

# Open the dashboard
docker compose run --rm openclaw-cli dashboard --no-open

Using Pre-Built Images (Skip the Build)

Building from source takes 3-8 minutes depending on your machine. If you want to skip that, use the official pre-built images from GitHub Container Registry:

Available tags:

Tag: `latest`, Description: Latest stable release

Tag: `main`, Description: Latest build from main branch (bleeding edge)

Tag: `2026.2.26`, Description: Specific version pin

For production, always pin a specific version:

The base image is `node:22-bookworm` with OCI annotations for traceability.

export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
./docker-setup.sh
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:2026.2.26"
./docker-setup.sh

Enabling Agent Sandboxing

By default, OpenClaw's agent can execute shell commands inside the gateway container. For stronger isolation, enable **sandbox mode** — this creates a separate Docker container for each agent session's tool execution.

This does several things: 1. Installs Docker CLI inside the OpenClaw image 2. Mounts the Docker socket into the gateway container 3. Configures `agents.defaults.sandbox.mode` in OpenClaw's settings 4. Builds the sandbox image (`openclaw-sandbox:bookworm-slim`)

Rootless Docker Socket

If you're running rootless Docker (recommended for security), specify the socket path:

Security Implications

Mounting `docker.sock` gives the container access to the Docker daemon — essentially root on the host. This is a deliberate tradeoff: sandbox isolation for agent tools, at the cost of Docker daemon access from the gateway container.

For a deeper dive on securing this setup, see our security hardening guide.

export OPENCLAW_SANDBOX=1
./docker-setup.sh
export OPENCLAW_SANDBOX=1
export OPENCLAW_DOCKER_SOCKET=/run/user/1000/docker.sock
./docker-setup.sh

Advanced: OpenClaw + Ollama (Multi-Container Setup)

One of the most popular Docker setups pairs OpenClaw with Ollama for local model inference. This gives you a completely self-hosted AI agent stack with zero API costs.

Create a `docker-compose.override.yml` in your OpenClaw repo root:

Then start everything together:

Docker Compose automatically merges `docker-compose.yml` and `docker-compose.override.yml`.

Configure OpenClaw to Use Ollama

Once Ollama is running, pull a model and configure OpenClaw:

In OpenClaw's configuration, set the Ollama endpoint. Since both containers are on the same Docker network, use the service name:

Resource Planning for Multi-Container

Setup: OpenClaw only, RAM Required: 1-2 GB, Disk Required: 2-3 GB

Setup: OpenClaw + Ollama (7B model), RAM Required: 6-8 GB, Disk Required: 8-10 GB

Setup: OpenClaw + Ollama (13B model), RAM Required: 12-16 GB, Disk Required: 15-20 GB

Setup: OpenClaw + Ollama + Sandbox, RAM Required: +1 GB per active session, Disk Required: +500 MB

For the best model choices with Ollama, see our dedicated comparison guide.

services:
  ollama:
    image: ollama/ollama:latest
    volumes:
      - ollama_data:/root/.ollama
    ports:
      - "11434:11434"
    restart: unless-stopped
    # Uncomment for GPU passthrough:
    # deploy:
    #   resources:
    #     reservations:
    #       devices:
    #         - driver: nvidia
    #           count: all
    #           capabilities: [gpu]

volumes:
  ollama_data:
docker compose up -d
# Pull a model
docker compose exec ollama ollama pull llama3.2

# Verify it's working
docker compose exec ollama ollama list
Model provider: ollama
Ollama URL: http://ollama:11434

Skip 60 minutes of setup — deploy in 60 seconds

DoneClaw handles Docker, servers, security, and updates. Your OpenClaw agent is ready to chat in under a minute.

Deploy Now

Environment Variables Reference

The Docker setup uses `.env` for configuration. Here's a complete reference:

Variable: `OPENCLAW_IMAGE`, Default: `openclaw:local`, Description: Docker image to use

Variable: `OPENCLAW_GATEWAY_TOKEN`, Default: (generated), Description: Authentication token for dashboard/API

Variable: `OPENCLAW_GATEWAY_PORT`, Default: `18789`, Description: Host port for web dashboard

Variable: `OPENCLAW_BRIDGE_PORT`, Default: `18790`, Description: Host port for device bridge

Variable: `OPENCLAW_GATEWAY_BIND`, Default: `lan`, Description: Bind mode: `lan`, `loopback`, or specific IP

Variable: `OPENCLAW_CONFIG_DIR`, Default: `~/.openclaw`, Description: Host path for config

Variable: `OPENCLAW_WORKSPACE_DIR`, Default: `~/.openclaw/workspace`, Description: Host path for workspace

Variable: `OPENCLAW_SANDBOX`, Default: (unset), Description: Enable sandbox: `1`, `true`, `yes`, `on`

Variable: `OPENCLAW_DOCKER_SOCKET`, Default: `/var/run/docker.sock`, Description: Docker socket path

Variable: `OPENCLAW_EXTRA_MOUNTS`, Default: (unset), Description: Comma-separated extra bind mounts

Variable: `OPENCLAW_HOME_VOLUME`, Default: (unset), Description: Named volume for `/home/node`

Variable: `OPENCLAW_DOCKER_APT_PACKAGES`, Default: (unset), Description: Extra apt packages for build

Variable: `OPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT`, Default: (Chromium default), Description: Limit browser renderer processes

Bind Mode Explained

The `OPENCLAW_GATEWAY_BIND` setting controls network exposure:

  • **`loopback`**: Only accessible from `127.0.0.1` — safest for local development
  • **`lan`**: Accessible from your local network — needed for Tailscale or LAN access
  • **Warning**: Docker's port mapping can bypass `loopback` binding on some systems. Always use firewall rules (`ufw`, `iptables`) as a second layer. See our Tailscale setup guide for zero-trust networking.

Extra Host Mounts

Need to give OpenClaw access to files outside the workspace? Use `OPENCLAW_EXTRA_MOUNTS`:

This generates a `docker-compose.extra.yml` that's automatically included. Each mount follows Docker's `source:target[:options]` format.

Common mounts:

export OPENCLAW_EXTRA_MOUNTS="$HOME/projects:/home/node/projects:ro,$HOME/.ssh:/home/node/.ssh:ro"
./docker-setup.sh
# Read-only access to your code repositories
$HOME/github:/home/node/github:ro

# SSH keys for git operations (read-only!)
$HOME/.ssh:/home/node/.ssh:ro

# Shared downloads folder
$HOME/Downloads:/home/node/Downloads:rw

ClawDock Shell Helpers

For day-to-day management, install the official shell helpers:

Available commands:

Command: `clawdock-start`, Description: Start the gateway

Command: `clawdock-stop`, Description: Stop the gateway

Command: `clawdock-restart`, Description: Restart the gateway

Command: `clawdock-dashboard`, Description: Print dashboard URL

Command: `clawdock-logs`, Description: Tail gateway logs

Command: `clawdock-status`, Description: Show container health

Command: `clawdock-update`, Description: Pull latest image and restart

Command: `clawdock-help`, Description: Show all available commands

mkdir -p ~/.clawdock && curl -sL \
  https://raw.githubusercontent.com/openclaw/openclaw/main/scripts/shell-helpers/clawdock-helpers.sh \
  -o ~/.clawdock/clawdock-helpers.sh

# Add to your shell (zsh example)
echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc
source ~/.zshrc

CI/CD and Automation

For headless environments (CI pipelines, cron jobs, automated deployments), disable TTY allocation:

The `-T` flag prevents Docker Compose from allocating a pseudo-TTY, which causes issues in non-interactive environments.

Automated Health Monitoring

Combine Docker's built-in health check with external monitoring:

docker compose run -T --rm openclaw-cli gateway probe
docker compose run -T --rm openclaw-cli devices list --json
#!/bin/bash
# health-check.sh — run via cron every 5 minutes
HEALTH=$(docker inspect --format='{{.State.Health.Status}}' openclaw-openclaw-gateway-1)
if [ "$HEALTH" != "healthy" ]; then
  echo "OpenClaw unhealthy: $HEALTH" | mail -s "OpenClaw Alert" [email protected]
  docker compose restart openclaw-gateway
fi

Updating OpenClaw in Docker

With Pre-Built Images

With Local Builds

Zero-Downtime Considerations

OpenClaw maintains persistent connections (WebSocket for Telegram, etc.), so restarts will briefly disconnect your messaging channels. They reconnect automatically within 10-30 seconds. For cron jobs and heartbeats, pending tasks resume after restart.

# Pull the latest image
docker compose pull openclaw-gateway

# Restart with the new image
docker compose up -d openclaw-gateway
# Pull latest source
git pull origin main

# Rebuild the image
docker compose build openclaw-gateway

# Restart
docker compose up -d openclaw-gateway

Troubleshooting Common Docker Issues

Exit Code 137 (OOM Killed)

**Symptom**: Container exits during build or startup with code 137.

**Cause**: Not enough RAM. The build phase (`pnpm install`) is memory-hungry.

**Fix**:

Or skip the build entirely with a pre-built image.

"Unauthorized" or "Disconnected (1008): Pairing Required"

**Symptom**: Dashboard shows disconnected or unauthorized errors.

**Fix**:

Port 18789 Already in Use

**Symptom**: `bind: address already in use`

**Fix**:

Container Can't Reach Ollama

**Symptom**: Connection refused when accessing Ollama from OpenClaw.

**Fix**: Make sure both services are on the same Docker network. If you're using `docker-compose.override.yml`, Docker Compose handles this automatically. If running Ollama separately:

Docker Socket Permission Denied (Sandbox Mode)

**Symptom**: `permission denied while trying to connect to the Docker daemon socket`

**Fix**:

Build Takes Too Long

**Symptom**: Local build takes 10+ minutes.

**Fix**: Use a pre-built image:

This reduces setup from minutes to seconds (just a `docker pull`).

# Check available memory
free -h

# For Docker Desktop, increase memory in Settings → Resources
# Minimum: 2 GB for build, 4 GB recommended

# On a VPS, add swap as a safety net:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# Get a fresh dashboard URL with token
docker compose run --rm openclaw-cli dashboard --no-open

# If that doesn't work, list and approve devices
docker compose run --rm openclaw-cli devices list
docker compose run --rm openclaw-cli devices approve <requestId>
# Find what's using the port
sudo lsof -i :18789

# Option 1: Kill the conflicting process
# Option 2: Change the port in .env
echo "OPENCLAW_GATEWAY_PORT=18800" >> .env
docker compose up -d
# Create a shared network
docker network create openclaw-net

# Run Ollama on that network
docker run -d --name ollama --network openclaw-net ollama/ollama

# Add the network to OpenClaw's compose
# In docker-compose.override.yml:
# services:
#   openclaw-gateway:
#     networks:
#       - openclaw-net
# networks:
#   openclaw-net:
#     external: true
# Check the Docker socket GID on your host
stat -c '%g' /var/run/docker.sock

# Set it in your .env or docker-compose
# group_add:
#   - "998"  # Replace with your actual Docker GID
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
./docker-setup.sh

Production Hardening Checklist

If you're running OpenClaw Docker in production (on a VPS or always-on server), follow this checklist:

Log Rotation

Docker logs can grow unbounded. Add to your `docker-compose.override.yml`:

Reverse Proxy with Caddy

A minimal Caddy setup for HTTPS:

Add Caddy to your compose stack or run it separately. This gives you automatic HTTPS via Let's Encrypt.

  • **Use `loopback` bind mode** unless you specifically need LAN access
  • **Set up a reverse proxy** (Nginx, Caddy, Traefik) with HTTPS
  • **Configure firewall rules** — Docker can bypass `ufw`; use `DOCKER-USER` chain
  • **Pin a specific image version** instead of `latest`
  • **Enable sandbox mode** for untrusted agent operations
  • **Set up log rotation** to prevent disk fill
  • **Monitor container health** with the built-in healthcheck
  • **Use Tailscale** for zero-trust remote access
  • **Back up** `~/.openclaw/` regularly — this contains your agent's memory and config
  • **Review the full** security hardening guide
services:
  openclaw-gateway:
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"
openclaw.yourdomain.com {
    reverse_proxy localhost:18789
}

Docker vs Native Install: When to Choose What

Factor: Setup time, Docker: 5-10 min, Native Install: 3-5 min

Factor: Isolation, Docker: Full container isolation, Native Install: Runs on host directly

Factor: Updates, Docker: Pull new image, restart, Native Install: `git pull`, rebuild

Factor: Resource overhead, Docker: ~100-200 MB extra, Native Install: None

Factor: Cleanup, Docker: Remove containers + volumes, Native Install: Manual uninstall

Factor: Multi-service, Docker: Docker Compose makes it easy, Native Install: Manual process management

Factor: Best for, Docker: VPS, production, multi-service, Native Install: Development, Raspberry Pi

For most users deploying on a VPS or wanting a clean setup, Docker is the recommended path. For development or resource-constrained devices, go native. Our complete deployment guide covers both approaches in detail.

Conclusion

Running OpenClaw in Docker is the cleanest way to deploy a personal AI agent — you get isolation, reproducibility, and easy multi-service composition out of the box. The `docker-setup.sh` script handles 90% of the work, and the Docker Compose architecture gives you a solid foundation to build on. Start with the quick setup, connect your preferred messaging channel, and you'll have a fully functional AI agent running in minutes. From there, layer on Ollama for local models, enable sandboxing for security, and add monitoring for production reliability. The Docker ecosystem around OpenClaw is maturing fast — between ClawDock helpers, pre-built GHCR images, and the growing community of Docker-first deployments, containerized OpenClaw is becoming the default for serious users.

Skip the setup? DoneClaw deploys OpenClaw for you — $29/mo with 7-day free trial, zero configuration.

Skip 60 minutes of setup — deploy in 60 seconds

DoneClaw handles Docker, servers, security, and updates. Your OpenClaw agent is ready to chat in under a minute.

Deploy Now

Frequently asked questions

Can I run OpenClaw Docker on a 1 GB VPS?

Technically, the runtime only needs about 1 GB of RAM. But the **build** phase requires at least 2 GB. The workaround: use a pre-built image (`OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"`) to skip the build entirely. With a pre-built image, a 1 GB VPS works for light usage, though 2 GB is recommended for comfortable operation. See our cheap VPS hosting guide for specific provider recommendations.

Does OpenClaw Docker work on ARM (Apple Silicon, Raspberry Pi)?

Yes. The official images support both `amd64` and `arm64` architectures. On Apple Silicon Macs, Docker Desktop handles this natively. On Raspberry Pi 4/5, you'll need at least 4 GB RAM for the Docker build. If you have a 2 GB Pi, use the native install instead — see our Raspberry Pi guide.

How do I connect Telegram/Discord/WhatsApp to the Docker setup?

The messaging channel setup works identically to native installs — the onboarding wizard handles it during `docker-setup.sh`. For Telegram specifically, you'll create a bot via @BotFather, provide the token during onboarding, then approve the pairing: ```bash docker compose run --rm openclaw-cli pairing approve telegram <CODE> ``` See our dedicated guides for Telegram, Discord, and WhatsApp.

How do I back up my OpenClaw Docker instance?

Back up the two host directories: ```bash tar czf openclaw-backup-$(date +%Y%m%d).tar.gz ~/.openclaw/ ``` This captures all configuration, API keys, agent memory, and workspace files. The Docker image itself doesn't need backing up — it's reproducible from the source or registry.

Can I run multiple OpenClaw instances on the same host?

Yes. Clone the repo to different directories and change the port mappings in `.env`: ```bash # Instance 1 (default ports) OPENCLAW_GATEWAY_PORT=18789 OPENCLAW_BRIDGE_PORT=18790 # Instance 2 OPENCLAW_GATEWAY_PORT=18791 OPENCLAW_BRIDGE_PORT=18792 ``` Also change `OPENCLAW_CONFIG_DIR` and `OPENCLAW_WORKSPACE_DIR` so each instance has its own data.