OpenClaw is an autonomous AI agent gateway that connects large language models to the real world. It can browse the web, execute code, manage files, send messages across platforms (Slack, Discord, Telegram, email, and more), and interact with external services — all driven by natural language instructions. You can think of it as a self-hosted, extensible AI agent that runs continuously and acts on your behalf.
In this workflow, we'll call our agent Clawde — a nod to both Claude (the underlying model) and OpenClaw.
- Docker Desktop installed and running
- An Anthropic API key (OpenClaw defaults to
anthropic/claude-opus-4-6)
Because OpenClaw is so capable, it can take over significant parts of your machine. Docker is the recommended way to run it because it limits the blast radius: if the agent does something unexpected, the damage is contained within the container and cannot affect the rest of your system.
Docker also brings the standard benefits of isolation, portability, and easy updates. Critically, by mounting ~/openclaw-config as a volume, your auth token, paired devices, and settings are persisted on the host and survive container restarts and replacements.
The official OpenClaw Docker image is:
ghcr.io/openclaw/openclaw:main-slim
This is the recommended image for most users. Alternatively, you can clone the OpenClaw GitHub repository and use the included Docker Compose file, which handles volume mounts, port bindings, and environment variables for you:
git clone https://github.com/openclaw/openclaw.git
cd openclaw
docker compose upThis workflow uses the official image with docker run for full control over the configuration.
mkdir -p ~/openclaw-config
cat > ~/openclaw-config/openclaw.json << 'EOF'
{
"gateway": {
"bind": "lan"
}
}
EOF
gateway.bind: "lan"is required so the gateway listens on0.0.0.0instead of127.0.0.1inside the container. Without this, Docker port forwarding can't reach the gateway. TheOPENCLAW_GATEWAY_BIND=lanenv var alone is not honored by themain-slimimage.
Create the workspace directory that Clawde will use to read and write files. Create it explicitly to avoid accidentally mounting an existing directory intended for another purpose:
mkdir -p ~/openclaw-workspaceThen start the container:
docker run -it \
-v ~/openclaw-workspace:/workspace \
-v ~/openclaw-config:/home/node/.openclaw \
-p 18789:18789 \
-p 18791:18791 \
--name openclaw \
ghcr.io/openclaw/openclaw:main-slimThe -p flags publish container ports to the host:
-p 18789:18789— the gateway port, used for WebSocket connections and serving the Control UI. This is the primary port you interact with from your browser.-p 18791:18791— the browser control server port, used internally by OpenClaw to manage browser automation. It always binds to127.0.0.1inside the container and is not accessible from the host — publishing it has no effect but is harmless.
Wait for startup. Confirm you see:
[gateway] listening on ws://0.0.0.0:18789 (PID 15)
Port 18791 (browser control) is always loopback-only by design and is not accessible from the host — this is expected.
docker exec openclaw node openclaw.mjs dashboard --no-openOutput will be:
Dashboard URL: http://127.0.0.1:18789/#token=<your-token>
Open the full URL from Step 3 (including #token=...) in your browser:
http://127.0.0.1:18789/#token=<your-token>
You will see the Gateway Dashboard with the WebSocket URL and token pre-filled.
- Set WebSocket URL to:
ws://127.0.0.1:18789 - Token should be pre-filled
- Click Connect
You will see "pairing required" — this is expected on first connection.
When running in Docker on macOS, the gateway inside the container sees browser connections coming from 192.168.65.1 (Docker Desktop's virtual network IP) rather than 127.0.0.1. Because the connection appears to originate from a non-loopback address, OpenClaw treats the browser as an unknown remote device and requires explicit pairing approval — even though the connection is actually from your local machine. This is a one-time step per browser; the approval is persisted in the config.
In a separate terminal, approve all pending pairing requests in one command:
docker exec openclaw node openclaw.mjs devices list --json \
--token $(jq -r '.gateway.auth.token' ~/openclaw-config/openclaw.json) | \
jq -r '.pending[].requestId' | \
xargs -I{} docker exec openclaw node openclaw.mjs devices approve \
--token $(jq -r '.gateway.auth.token' ~/openclaw-config/openclaw.json) {}Click Connect again in the browser. The dashboard, or Control UI, should now connect successfully.
The dashboard is accessible at:
http://127.0.0.1:18789/
On restart, the config and auth token are persisted in ~/openclaw-config/. No need to repeat Steps 1–2. Just:
docker start openclawThen open the dashboard URL from Step 3. The browser device pairing (Steps 5–6) is also persisted and won't need to be repeated unless you clear the config or use a new browser.
To stop and remove the container:
docker rm -f openclawTo also wipe the config (auth token, paired devices, settings) for a full reset:
rm -rf ~/openclaw-configOnly do this if you want to start completely fresh — you will need to re-pair your browser on next start.
This blog covered getting Clawde up and running in Docker. Future posts will explore connecting Clawde to messaging platforms, giving it tools and skills, and putting it to work on real-world tasks.