🐳Container

Self-Host OpenClaw with Docker

Run OpenClaw locally or on any server using Docker and Docker Compose. Complete guide covering installation, configuration, persistent storage, and remote access.

Difficulty: beginnerTime: ~15 minCost: N/A

Self-Host OpenClaw with Docker

Docker is the most portable way to run OpenClaw on any machine. Whether you are on a laptop, a VPS, or a bare-metal server, Docker Compose gives you a reproducible single-command setup with persistent storage and sensible defaults. This guide covers installation, configuration, networking, and day-to-day operations.

Quick Path

For developers with Docker already installed:

  1. Clone the OpenClaw repository: git clone https://github.com/openclaw/openclaw.git && cd openclaw
  2. Copy the example environment file: cp .env.example .env
  3. Edit .env and set ANTHROPIC_API_KEY and OPENCLAW_GATEWAY_TOKEN
  4. Run docker compose up -d --build
  5. Open http://localhost:18789 and authenticate with your gateway token

Prerequisites

Install Docker

If Docker is not installed yet:

# macOS
brew install --cask docker

# Ubuntu/Debian
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Log out and back in for group changes to take effect

# Verify installation
docker --version
docker compose version

Project Setup

Clone the Repository

git clone https://github.com/openclaw/openclaw.git
cd openclaw

Create the Environment File

Copy the example and fill in your values:

cp .env.example .env

Edit .env with the following variables:

# Container image (use a specific tag for reproducibility)
OPENCLAW_IMAGE=openclaw/openclaw:latest

# Gateway authentication token — generate a strong random value
OPENCLAW_GATEWAY_TOKEN=your-secret-token-here

# Network binding — "lan" exposes to the Docker network, "loopback" restricts to localhost
OPENCLAW_GATEWAY_BIND=lan

# Gateway port
OPENCLAW_GATEWAY_PORT=18789

# Paths inside the container for configuration and workspace
OPENCLAW_CONFIG_DIR=/home/node/.openclaw
OPENCLAW_WORKSPACE_DIR=/home/node/.openclaw/workspace

# Required for the container's internal keyring
GOG_KEYRING_PASSWORD=any-passphrase-here

# XDG base directory for OpenClaw config files
XDG_CONFIG_HOME=/home/node/.openclaw

# LLM provider API key (set at least one)
ANTHROPIC_API_KEY=sk-ant-your-key-here
# OPENAI_API_KEY=sk-your-key-here
# OPENROUTER_API_KEY=sk-or-your-key-here

Generate a strong gateway token:

openssl rand -hex 32

Copy the output into the OPENCLAW_GATEWAY_TOKEN field in your .env file.

Docker Compose Configuration

The docker-compose.yml file defines the complete service:

version: "3.8"

services:
  openclaw:
    build:
      context: .
      dockerfile: Dockerfile
    image: ${OPENCLAW_IMAGE:-openclaw/openclaw:latest}
    restart: unless-stopped
    env_file:
      - .env
    environment:
      - OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
      - OPENCLAW_GATEWAY_BIND=${OPENCLAW_GATEWAY_BIND:-lan}
      - OPENCLAW_GATEWAY_PORT=${OPENCLAW_GATEWAY_PORT:-18789}
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
      - OPENAI_API_KEY=${OPENAI_API_KEY:-}
      - OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
      - GOG_KEYRING_PASSWORD=${GOG_KEYRING_PASSWORD}
      - XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-/home/node/.openclaw}
    volumes:
      - openclaw-config:/home/node/.openclaw
      - openclaw-workspace:/home/node/.openclaw/workspace
    ports:
      - "127.0.0.1:18789:18789"
    command: ["node", "dist/index.js", "gateway"]
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:18789/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s

volumes:
  openclaw-config:
  openclaw-workspace:

Key details:

Build and Launch

Build the image and start the service in detached mode:

docker compose up -d --build

Watch the logs to confirm a successful start:

docker compose logs -f openclaw

You should see output indicating the gateway is listening:

Gateway listening on 0.0.0.0:18789
Health check endpoint: /health

Verify the container is healthy:

docker compose ps

The STATUS column should show Up with (healthy) after the start period.

Accessing OpenClaw

Local Access

Open your browser and navigate to:

http://localhost:18789

Authenticate with the OPENCLAW_GATEWAY_TOKEN you set in the .env file.

Remote Access via SSH Tunnel

If OpenClaw is running on a remote server, create an SSH tunnel instead of exposing the port publicly:

ssh -L 18789:localhost:18789 user@your-server

Then open http://localhost:18789 on your local machine. The traffic is encrypted through the SSH connection.

Remote Access via Tailscale

For persistent remote access without port forwarding, install Tailscale on both your local machine and the server:

# On the server running OpenClaw
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

Then access OpenClaw at http://your-server-tailscale-ip:18789. Tailscale handles encryption and authentication through your tailnet.

State and Persistence

OpenClaw stores all state in the mounted volumes:

PathContentsVolume
~/.openclaw/openclaw.jsonRuntime configurationopenclaw-config
~/.openclaw/agents/Agent definitions and instructionsopenclaw-config
~/.openclaw/workspace/Project files and session dataopenclaw-workspace

These volumes survive container rebuilds. To back them up:

# Create a tarball of all OpenClaw data
docker run --rm \
  -v openclaw-config:/config \
  -v openclaw-workspace:/workspace \
  -v $(pwd):/backup \
  alpine tar czf /backup/openclaw-backup-$(date +%Y%m%d).tar.gz /config /workspace

To restore from a backup:

docker run --rm \
  -v openclaw-config:/config \
  -v openclaw-workspace:/workspace \
  -v $(pwd):/backup \
  alpine sh -c "cd / && tar xzf /backup/openclaw-backup-20260413.tar.gz"

Customizing the Configuration

Edit Runtime Config

To modify openclaw.json while the container is running:

docker compose exec openclaw cat /home/node/.openclaw/openclaw.json
docker compose exec openclaw sh -c 'cat > /home/node/.openclaw/openclaw.json << EOF
{
  "model": "claude-sonnet-4-20250514",
  "permissions": {
    "allow_network": true,
    "allow_file_write": true
  }
}
EOF'

Restart the container to pick up changes:

docker compose restart openclaw

Edit Agent Instructions

Agent instruction files live in the agents/ directory inside the config volume:

docker compose exec openclaw sh -c 'cat > /home/node/.openclaw/agents/AGENTS.md << EOF
# Agent Instructions

You are a coding assistant. Follow project conventions.
Always run tests before proposing changes.
EOF'

Add Model Providers

Uncomment or add the relevant API key in your .env file:

OPENAI_API_KEY=sk-your-openai-key
OPENROUTER_API_KEY=sk-or-your-openrouter-key

Then restart the service:

docker compose up -d

Security Best Practices

Troubleshooting

Container exits immediately

Check the logs for error messages:

docker compose logs openclaw

Common causes:

Cannot connect to localhost:18789

Verify the container is running and healthy:

docker compose ps

If the container is running but you cannot connect, check that the port mapping is correct and no firewall is blocking local connections.

Permission denied errors in the container

The container runs as the node user (UID 1000). If the mounted volumes were created by root, the container cannot write to them. Fix permissions:

docker compose down
docker run --rm -v openclaw-config:/data alpine chown -R 1000:1000 /data
docker run --rm -v openclaw-workspace:/data alpine chown -R 1000:1000 /data
docker compose up -d

Builds are slow

Docker layer caching speeds up subsequent builds. If the cache is being invalidated unnecessarily, check that your .dockerignore excludes large directories like node_modules/, .git/, and test fixtures.

Health check failing

The health check runs curl -f http://localhost:18789/health inside the container. If curl is not available in the image, replace the health check with a TCP check:

healthcheck:
  test: ["CMD-SHELL", "node -e \"require('http').get('http://localhost:18789/health', r => process.exit(r.statusCode === 200 ? 0 : 1))\""]

Updating OpenClaw

Pull the latest changes and rebuild:

cd openclaw
git pull origin main
docker compose up -d --build

The named volumes are not affected by the rebuild. Your configuration, agent instructions, and workspace data remain intact.

To update without rebuilding from source (using a pre-built image):

docker compose pull
docker compose up -d

Frequently Asked Questions

Can I run OpenClaw with Docker on Windows?

Yes. Install Docker Desktop for Windows with the WSL 2 backend enabled. The Docker Compose setup works the same way. Performance is best when your project files live inside the WSL filesystem rather than on the Windows host.

How do I access OpenClaw from another machine on my network?

Change the port binding in docker-compose.yml from 127.0.0.1:18789:18789 to 0.0.0.0:18789:18789. Then access the gateway at http://your-server-ip:18789. Make sure you have the gateway token and consider using an SSH tunnel or Tailscale instead of opening the port directly.

Will my data survive a Docker Compose rebuild?

Yes. The docker-compose.yml mounts named volumes for configuration and workspace data. These volumes persist across container rebuilds, restarts, and image updates. Only an explicit docker volume rm deletes the data.

Can I use a GPU with OpenClaw in Docker?

OpenClaw itself does not require a GPU — inference happens on the remote LLM provider. If you are running a local model server alongside OpenClaw, configure the GPU passthrough on that container, not the OpenClaw container.

SuperBuilder

Prefer a managed experience?

SuperBuilder runs OpenClaw with zero setup — cloud execution, cost tracking, and team collaboration built in.

Try SuperBuilder Free