Skip to content

OpenClaw Docker Deployment: The Config Trap No Tutorial Mentions

docker-setup.sh gets you started in 5 minutes - but CLI commands silently fail and the dashboard shows 'pairing required'. Here's the Docker networking fix every tutorial skips.

7 min readIntermediate

Two ways to deploy OpenClaw in Docker: run docker-setup.sh and be online in 5 minutes, or write your own docker-compose.yml and control every variable. The first works until you need CLI commands or non-localhost access. The second requires understanding what the script actually does.

The trade-off. Script handles volumes, env vars, onboarding, starts the gateway automatically. But – it makes network assumptions that break in Docker Desktop on Windows, VPS deployments behind reverse proxies, anywhere the CLI container needs to talk to the gateway container.

What the Official Script Does (And Hides)

The official docker-setup.sh script clones the repo, builds a local image, creates two directories (~/.openclaw for config, ~/openclaw/workspace for agent files), runs an onboarding wizard for API keys, launches the gateway via Compose.

What it doesn’t tell you: openclaw-cli container doesn’t share the gateway’s network namespace by default. CLI commands try ws://127.0.0.1:18789 – in Docker that’s the CLI container’s own loopback, not the gateway. Connection fails with ECONNREFUSED. GitHub Issue #11456 documents this.

Fix is in the issue thread, not the setup guide: add network_mode: "service:openclaw-gateway" to openclaw-cli service. The script does write this to docker-compose.extra.yml – but only if you set certain env vars first. Run the script without reading source? You won’t know the file exists.

Running the Official Setup

Clone and run:

git clone https://github.com/openclaw/openclaw.git
cd openclaw
./scripts/docker/setup.sh

Wizard asks: Gateway mode (choose local unless deploying to remote server), Network bind (lan for host browser access, loopback for container-only), LLM provider (Anthropic, OpenAI, Google, local Ollama – wizard writes API key to .env).

Wait 40-60 seconds. Gateway takes time. You’ll see [entrypoint] Starting OpenClaw gateway first – not the ready signal. Wait for [gateway] listening on ws://127.0.0.1:18789.

Open http://localhost:18789. Authentication error. Gateway requires a token:

docker compose run --rm openclaw-cli dashboard --no-open

Copy the URL with ?token=..., paste into browser.

The Docker Desktop Windows Trap

Dashboard loads but shows disconnected (1008): pairing required. You entered the token correctly. Still doesn’t work.

NAT. Browser connects to http://localhost:18789, Docker Desktop’s networking layer translates that to the container’s IP. Gateway sees the connection from 172.18.0.1 (Docker’s bridge network), not 127.0.0.1. OpenClaw treats non-localhost as external, requires device pairing – browser can’t complete.

Issue #4941 shows gateway logs: remote=172.18.0.1 code=1008 reason=pairing required. Two config changes in ~/.openclaw/openclaw.json:

{
 "gateway": {
 "auth": {
 "mode": "token",
 "token": "your-token-here"
 },
 "controlUi": {
 "allowInsecureAuth": true
 },
 "trustedProxies": ["172.18.0.0/16"]
 }
}

allowInsecureAuth: gateway accepts token auth from proxied connections. trustedProxies: trust requests from Docker’s bridge network range. Restart after editing.

Pro tip: Deploying behind a reverse proxy (Traefik, Caddy, Nginx)? Same issue. Add your proxy’s IP range to trustedProxies and set gateway.controlUi.allowedOrigins to include your public domain. Otherwise: “origin not allowed” errors when accessing from anything but localhost.

Manual Deployment: Full Control, More Config

Need to customize – run multiple instances, integrate with existing networks, VPS with specific volume mounts – write your own docker-compose.yml.

Minimal working config:

version: '3.8'

services:
 openclaw-gateway:
 image: ghcr.io/openclaw/openclaw:latest
 container_name: openclaw
 restart: unless-stopped
 ports:
 - "18789:18789"
 volumes:
 - ~/.openclaw:/home/node/.openclaw
 - ~/openclaw/workspace:/home/node/.openclaw/workspace
 environment:
 - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
 - OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
 init: true

 openclaw-cli:
 image: ghcr.io/openclaw/openclaw:latest
 network_mode: "service:openclaw-gateway"
 volumes:
 - ~/.openclaw:/home/node/.openclaw
 profiles: ["cli"]

Create .env:

ANTHROPIC_API_KEY=sk-ant-...
OPENCLAW_GATEWAY_TOKEN=your-random-token

network_mode: "service:openclaw-gateway" – critical. Without it? CLI commands fail. profiles: ["cli"] prevents CLI container from auto-starting – you only need it when running commands.

Start gateway:

docker compose up -d openclaw-gateway

Run CLI:

docker compose run --rm openclaw-cli devices list

Config Conflicts: When Env Vars Override JSON

You set gateway.bind = "lan" in openclaw.json. Restart. Logs still show [gateway] listening on ws://127.0.0.1:18789. Gateway ignores your config.

This is Issue #43886. OpenClaw reads config in order: environment variables (highest), command-line flags, openclaw.json (lowest).

If docker-compose.yml sets OPENCLAW_GATEWAY_BIND=loopback or GATEWAY_MODE=local, those override JSON. Gateway binds to 127.0.0.1 only. External connections fail.

Check running container’s env vars:

docker exec openclaw env | grep OPENCLAW

See OPENCLAW_GATEWAY_BIND=loopback? Remove from docker-compose.yml, restart. Or keep the env var, delete the conflicting line from openclaw.json. Pick one source of truth.

Permission Errors on Linux

Official image runs as node user (uid 1000). Host directories not owned by uid 1000? Container can’t write to ~/.openclaw. EACCES errors in logs.

Fix:

sudo chown -R 1000:1000 ~/.openclaw ~/openclaw/workspace

Doesn’t come up on macOS/Windows – Docker Desktop handles UID mapping. Linux: set it manually.

Docker vs Other Deployment Methods

Method Pros Cons
docker-setup.sh Fast setup, handles onboarding, works on all platforms CLI networking issues on some setups, hidden config in extra files, less control
Manual docker-compose Full control, easy to version and replicate, explicit config Requires Docker networking knowledge, more initial setup, manual onboarding
Direct npm install No Docker overhead, direct file access, easier debugging No isolation, requires Node 22+, PATH issues, can break system packages
Managed hosting Zero config, handles updates, no server maintenance Costs $45-200/month, less customization, data on third-party servers

Docker sits in the middle. More isolated than direct install, more complex than managed hosting. For most developers? Right choice. You control your data, customize the setup, don’t manage Node.js versions or global npm packages.

What to Do Next

Gateway running, dashboard connects? Add a messaging channel. Telegram: fastest. Create bot via @BotFather, get API token:

docker compose run --rm openclaw-cli channels add --channel telegram --token "YOUR_TOKEN"

Send message to your bot. OpenClaw replies with pairing code. Approve:

docker compose run --rm openclaw-cli pairing approve telegram CODE

Control OpenClaw from your phone. Test: “what’s the current time” or “list files in the workspace.” Responds? Deployment works. Doesn’t? Check logs:

docker logs openclaw --tail 50

Look for API key errors, model selection issues, rate limit warnings. Most failures happen at the LLM provider layer, not Docker.

Actually – one thing nobody mentions. The gateway takes 40-60 seconds to start, but docker compose up reports “up” immediately. Send requests before [gateway] listening on appears? Connection refused. The [entrypoint] Starting OpenClaw gateway line lies. Wait for the real signal.

FAQ

Why does docker compose run --rm openclaw-cli fail with connection refused?

CLI container doesn’t share gateway’s network. Add network_mode: "service:openclaw-gateway" to openclaw-cli in docker-compose.yml or use docker-compose.extra.yml if the setup script made one.

Can I run OpenClaw on a Raspberry Pi?

Yes. Official image supports ARM64. Use ghcr.io/openclaw/openclaw:latest on Pi 4 with 4GB+ RAM. A Pi 4 draws ~5W – running 24/7 costs $5/year in electricity, cheaper than any VPS. Response times slower if using cloud models over residential internet, but it works. Turns out the bottleneck isn’t the Pi’s CPU – it’s API latency. Claude’s endpoint takes 2-4 seconds to respond regardless of where you call from. The Pi adds maybe 50ms of processing overhead. Your home upload speed matters more than the hardware.

How do I update OpenClaw after deploying with Docker?

Pull latest image, stop container, recreate. Config and workspace persist in mounted volumes – updates are non-destructive: docker compose pull && docker compose up -d. Gateway restarts with new version. Check logs to confirm success. Running a specific version tag (e.g., 2026.2.26) instead of latest? Update the tag in docker-compose.yml before pulling. One catch: if the new version changes config schema, you might need to migrate openclaw.json. The release notes usually mention this, but not always. Safe bet: back up ~/.openclaw before updating. Had one update that renamed gateway.auth.token to gateway.controlUi.authToken – old config broke silently until I checked the changelog.