I watched the setup wizard finish. “Onboarding complete,” it said. Then nothing.
The terminal just sat there. No prompt. No gateway. The container was technically running, but OpenClaw wasn’t responding. This wasn’t a crash – it was worse. A hang.
Turns out there’s a token handoff problem between the CLI container and the gateway that most tutorials never mention. The wizard generates one token. Docker Compose writes a different one to .env. The CLI tries to connect, fails with a 1006 websocket error, and you’re stuck.
This isn’t in the official quickstart. It’s buried in GitHub issue #9028 and Discord threads. Here’s what actually works.
Why Docker Isolation Matters for OpenClaw
OpenClaw isn’t a chatbot. It’s an autonomous agent that executes shell commands, reads files, writes code, and modifies your system. The official repository (356,211 stars as of April 2026) integrates with WhatsApp, Telegram, Slack – anywhere you can send a message becomes a remote terminal into your machine.
That’s powerful. Also risky.
Docker is the containment layer. Files OpenClaw creates land in a mounted workspace directory, not scattered across your home folder. API keys stay in container volumes. Something goes sideways? Delete the container, start fresh.
But Docker also introduces failure modes. Permission mismatches. Port conflicts. The token handoff problem we’re about to fix.
Prerequisites and System Requirements
Docker Desktop (or Docker Engine) with Compose v2. Minimum 2GB RAM – pnpm install will OOM-kill on 1GB hosts with exit code 137 (official Docker docs). An API key from Anthropic, OpenAI, or Google.
Clone the repository:
git clone https://github.com/openclaw/openclaw.git
cd openclaw
Check your Docker version:
docker compose version
If it says “command not found,” you’re on the old docker-compose (with a hyphen). Update to Compose v2 before continuing.
The Setup Script – And Where It Hangs
The repository includes ./scripts/docker/setup.sh. It builds the gateway image, runs the onboarding wizard, dumps config to .env, starts the gateway.
Run it:
./scripts/docker/setup.sh
The wizard asks which LLM provider (Anthropic, OpenAI, Google), your API key, whether to enable Tailscale mesh networking. Answer the prompts. “Onboarding complete” appears. You expect the gateway to start.
Instead: the terminal hangs. docker ps shows an openclaw-openclaw-cli-run-... container running for 6+ minutes. No gateway. No dashboard URL.
This is the token mismatch. The CLI can’t authenticate because OPENCLAW_GATEWAY_TOKEN in .env doesn’t match what the wizard configured. The CLI loops trying to connect, the wizard never exits, you’re stuck.
The Fix
Stop the hanging setup (Ctrl+C). Start the gateway manually:
docker compose up -d openclaw-gateway
Wait 30 seconds. Gateway initializes. Get a fresh dashboard token:
docker compose run --rm openclaw-cli dashboard --no-open
Prints a URL with ?token=... at the end. Open it. Dashboard loads.
If the CLI still can’t connect (websocket 1006 or 1008 errors), check the gateway logs:
docker compose logs openclaw-gateway --tail 50
Look for “token mismatch” or “pairing required.” Pairing errors? Approve the CLI device:
docker compose run --rm openclaw-cli devices list
docker compose run --rm openclaw-cli devices approve <requestId>
This happens when the gateway enforces pairing mode but the CLI hasn’t been approved yet. It’s in issue #9028 but not the main install guide.
Volume Permissions – The uid 1000 Trap
OpenClaw’s Docker image runs as user node with uid 1000. Your host user has a different uid? You’ll see permission errors when the container tries to write to ~/.openclaw or ~/openclaw/workspace.
Symptom: logs show “EACCES: permission denied” or “cannot create directory.”
Check ownership:
ls -la ~/.openclaw
ls -la ~/openclaw/workspace
Owned by your user (e.g., uid 1001)? Change them:
sudo chown -R 1000:1000 ~/.openclaw ~/openclaw/workspace
Restart the gateway:
docker compose restart openclaw-gateway
Permission errors stop. This is in the official Docker docs but easy to miss.
Sandbox Isolation – The Silent Downgrade
OpenClaw supports running agent tools (shell exec, file read/write) inside nested Docker containers for extra isolation. The agents.defaults.sandbox setting.
You enable it during setup. Wizard tries to configure sandbox mode. Setup fails – missing /var/run/docker.sock mount, insufficient Docker resources, permission issues – and docker-setup.sh silently resets sandbox.mode to off.
You think sandbox is enabled. It’s not.
Check the actual config:
docker compose exec openclaw-gateway cat /home/node/.openclaw/openclaw.json | grep -A 5 sandbox
If "mode": "off", sandbox didn’t initialize. Fix: make sure the Docker socket is mounted. Edit docker-compose.yml:
services:
openclaw-gateway:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Recreate the container:
docker compose down
docker compose up -d openclaw-gateway
Enable sandbox in the config. Open ~/.openclaw/openclaw.json, find agents.defaults.sandbox:
"sandbox": {
"mode": "all",
"backend": "docker",
"scope": "session"
}
Restart the gateway. Agent commands now run in isolated containers. Default network is none (sandboxing docs) – containers have no internet unless you explicitly set docker.network.
The tradeoff: added security, but skills that need network access (curl, package installs) will fail unless you configure egress.
Pro tip: Use
sandbox.mode: "non-main"instead of"all"if you want your primary chat session to run on the host for speed, while isolating secondary tasks. Faster for interactive work, still sandboxes background jobs.
Port Conflicts and Dashboard Access
Default gateway port: 18789. Something else using it? Container won’t start.
Check:
lsof -i :18789 # macOS/Linux
netstat -ano | findstr 18789 # Windows
Occupied? Change the port in .env:
OPENCLAW_GATEWAY_PORT=18790
Restart Compose:
docker compose down
docker compose up -d openclaw-gateway
Dashboard is at http://localhost:18790 now. Get the token URL again:
docker compose run --rm openclaw-cli dashboard --no-open
Browser caches the old token sometimes. See “Unauthorized”? Clear site data or use incognito.
Connecting a Channel (Telegram)
Dashboard chat works, but talking to OpenClaw from your phone is the real use case. Telegram is fastest.
Create a bot via @BotFather on Telegram. Copy the token. Add the channel:
docker compose run --rm openclaw-cli channels add --channel telegram --token "YOUR_BOT_TOKEN"
Pair your Telegram account:
docker compose run --rm openclaw-cli pairing approve telegram <CODE>
Bot sends you a pairing code. Paste it into the command above. Message the bot. It replies. You’re in.
When the Container Exits Immediately
docker ps shows nothing, docker compose logs shows exit code 137? OOM kill. Docker didn’t have enough RAM during the build.
Increase Docker’s memory limit (Docker Desktop → Settings → Resources → Memory) to at least 4GB. Rebuild:
docker compose down
docker compose build --no-cache
docker compose up -d openclaw-gateway
Exit code 1 or 2 usually means a missing environment variable. Check .env:
cat .env
Make sure ANTHROPIC_API_KEY (or whichever provider you chose) is set and starts with the right prefix (sk-ant- for Anthropic, sk- for OpenAI).
Updating OpenClaw in Docker
OpenClaw releases frequently. Version 2026.4.14 was published April 2026 (from package.json). To update:
cd openclaw
git pull
docker compose build --no-cache
docker compose down
docker compose up -d openclaw-gateway
Config and workspace volumes persist. Container recreates with the new code.
Using a prebuilt image (ghcr.io/openclaw/openclaw:latest)? Pull the new image:
docker compose pull
docker compose up -d openclaw-gateway
What You Built
OpenClaw running in a Docker container. Gateway on port 18789. API keys and config in ~/.openclaw. Agent workspace: ~/openclaw/workspace. Message it via Telegram or the web dashboard.
You fixed the token handoff problem that stops most people during setup. You know how to check volume permissions, verify sandbox mode, recover from OOM kills.
Next: connect it to WhatsApp (channels login --channel whatsapp, scan the QR code), add skills from ClawHub, or set up cron jobs for scheduled tasks. The official docs cover all of that.
Or just leave it running and see what happens when you tell it to automate something.
FAQ
Why does the setup script hang after “Onboarding complete”?
Token mismatch. Wizard writes one token, Compose writes another to .env. CLI can’t authenticate (websocket 1006/1008), loops forever. Fix: docker compose up -d openclaw-gateway, then docker compose run --rm openclaw-cli dashboard --no-open for a fresh token URL.
What’s the difference between running OpenClaw in Docker vs. native install?
Docker adds isolation – agent file writes stay in the container workspace, not your home directory. Easier to reset (delete container, start fresh). Downside: extra layer of complexity (volume permissions, network config, sandbox-in-Docker). Native install is faster for local dev, but if OpenClaw does something unexpected, it has full host access. Docker limits the blast radius. Simon Willison’s writeup chose Docker specifically because he wasn’t “brave enough” to run it directly on his Mac (good instinct for something that executes arbitrary shell commands).
Can I run OpenClaw on a VPS with Docker, and should I enable sandbox mode?
Yes. DigitalOcean, Hetzner, others support Docker deployments. Exposing it to the internet? Enable sandbox mode (agents.defaults.sandbox.mode: "all") and mount /var/run/docker.sock so agent commands run in isolated containers. Without sandbox, a compromised agent has full access to your gateway container (API keys, bot tokens, credentials). With sandbox (issue #29933), the agent runs in a separate container with no access to the gateway’s /data/.openclaw directory. Set sandbox.docker.network: "none" to block outbound connections unless you explicitly need them. Firewall port 18789 – never expose the dashboard publicly without strong authentication.