TL;DR: OpenClaw ships an official Docker setup: run
./scripts/docker/setup.shfrom the repository and it builds the image, runs onboarding, writes a gateway token and starts the gateway with Docker Compose. The parts that trip people up are the split between the gateway and CLI containers, which paths actually persist, the bind mode, and file ownership for uid 1000.
Contents
- Should You Run OpenClaw in Docker?
- Install OpenClaw With Docker Compose
- The Gateway and CLI Containers
- What Persists in an OpenClaw Docker Install
- Networking: LAN vs Loopback Bind
- Common OpenClaw Docker Errors
- Updating OpenClaw in Docker
- Docker Gateway vs Agent Sandbox
Should You Run OpenClaw in Docker?
Run OpenClaw in Docker when you want the gateway isolated from the host, such as on a server or in a disposable test environment. On your own laptop, the normal npm install is faster to work with. OpenClaw’s own documentation describes Docker as optional, not as the recommended default.
Docker earns its place in three situations:
- A server or VPS where you do not want Node and its dependencies installed on the host.
- A throwaway environment to test a new version or a risky config change before it touches your real setup.
- A repeatable install that you can rebuild from the same compose file every time.
If you are new to OpenClaw, start with our OpenClaw tutorial on a normal install, then move to Docker once you know what a working gateway looks like.
You need Docker Engine or Docker Desktop with Compose v2, and at least 6 GB of RAM to build the image from source; a pre-built image skips that requirement. On a smaller host the build’s pnpm install step can be killed with exit code 137.
Install OpenClaw With Docker Compose
The official OpenClaw Docker install is one script: clone the repository and run ./scripts/docker/setup.sh from its root. The script builds the image, runs onboarding, generates a gateway token, writes it to .env and starts the gateway with Docker Compose.
Clone the repository and change into it:
git clone https://github.com/openclaw/openclaw cd openclawRun the setup script. It prompts for your model provider API keys during onboarding:
./scripts/docker/setup.shTo skip the local build and use the published image from the GitHub Container Registry, set
OPENCLAW_IMAGEfirst:export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest" ./scripts/docker/setup.shOpen
http://127.0.0.1:18789/and paste the token from.envinto Settings. If you lose the link, print it again:docker compose run --rm openclaw-cli dashboard --no-open
Run every docker compose command from the repository root. If you set OPENCLAW_EXTRA_MOUNTS or OPENCLAW_HOME_VOLUME, the script also writes docker-compose.extra.yml, and you need to pass both files with -f docker-compose.yml -f docker-compose.extra.yml.
The official images carry tags such as latest, main and version numbers. Pin a version tag on a server, so an update happens when you choose rather than on the next pull.
OpenClaw Docker compose: the manual flow
If you would rather run each step yourself, the documented manual flow is:
docker build -t openclaw:local -f Dockerfile .
docker compose run --rm --no-deps --entrypoint node openclaw-gateway \
dist/index.js onboard --mode local --no-install-daemon
docker compose run --rm --no-deps --entrypoint node openclaw-gateway \
dist/index.js config set --batch-json '[{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"lan"},{"path":"gateway.controlUi.allowedOrigins","value":["http://localhost:18789","http://127.0.0.1:18789"]}]'
docker compose up -d openclaw-gateway
Note that onboarding and the config writes go through openclaw-gateway, not openclaw-cli. The next section explains why.
The Gateway and CLI Containers
An OpenClaw Docker install runs two services: openclaw-gateway, which is the long-running gateway, and openclaw-cli, which runs one-off commands against it. The CLI container shares the gateway’s network namespace, so it can only reach a gateway that is already running.
That is the most common source of confusion in the Docker flow. Before the gateway container exists, commands such as onboarding and setup-time config writes have to run through the gateway service with --no-deps --entrypoint node. After docker compose up -d openclaw-gateway, use the CLI container for everything else:
docker compose run --rm openclaw-cli channels add --channel telegram --token "<token>"
docker compose run --rm openclaw-cli devices list
The first command adds a Telegram channel; the second lists devices waiting for pairing.
In scripts and CI, add -T to turn off the pseudo-TTY, for example docker compose run -T --rm openclaw-cli gateway probe.
Because the two containers share a network namespace, treat them as one trust boundary. The shipped compose file drops NET_RAW and NET_ADMIN on both the gateway and CLI containers and sets no-new-privileges. If you edit it, keep those settings.
What Persists in an OpenClaw Docker Install
Only the bind-mounted config and workspace directories survive a container rebuild; everything else in the container is disposable. Compose mounts OPENCLAW_CONFIG_DIR to /home/node/.openclaw and OPENCLAW_WORKSPACE_DIR to /.
| What | Path in the container | Survives a rebuild? |
|---|---|---|
Gateway config (openclaw.json) and .env | /home/node/.openclaw/ | Yes, host bind mount |
| Model auth profiles (API keys, OAuth) | / | Yes, host bind mount |
| Skill state | /home/node/.openclaw/skills/ | Yes, host bind mount |
| Agent workspace | / | Yes, host bind mount |
| Extra binaries and OS packages | Container filesystem | No, bake them into the image |
| The container itself | Ephemeral | No, and it is safe to destroy |
Two rules follow from that table. First, never install a tool inside a running container and expect it to stay; set OPENCLAW_IMAGE_APT_PACKAGES before the build, for example "git curl jq", so the package is in the image.
Second, back up the config directory, because it holds your gateway token and provider credentials. Our guide to OpenClaw gateway token management covers how that token is used.
Watch disk use on long-running installs. The documented growth spots are media/, session JSONL files, cron/runs/*.jsonl and the rolling logs under /tmp/openclaw/.
Networking: LAN vs Loopback Bind
The OpenClaw Docker setup binds the gateway to lan so the published port 18789 is reachable from the host; loopback keeps it inside the container’s network. If the Control UI will not load from your browser, the bind mode is the first thing to check.
lan(the Docker default): your host browser and host CLI can reachhttp://127.0.0.1:18789.loopback: only processes inside the container’s network namespace can reach the gateway.
Set gateway.bind to one of OpenClaw’s bind mode values: lan, loopback, custom, tailnet or auto. An address such as 0.0.0.0 or 127.0.0.1 is not a valid bind value.
On a VPS, lan plus a published port can expose the gateway to the internet. Docker’s port publishing bypasses many host firewalls, so read OpenClaw’s network security guidance on the DOCKER-USER firewall chain before you open the port. Our list of OpenClaw production gotchas covers other failures that stay silent until they cost you.
The gateway also exposes two unauthenticated probe endpoints, which the image’s built-in HEALTHCHECK uses:
curl -fsS http://127.0.0.1:18789/healthz # liveness
curl -fsS http://127.0.0.1:18789/readyz # readiness
Common OpenClaw Docker Errors
Most OpenClaw Docker errors come from four causes: file ownership, the bind mode, device pairing and a build host with too little memory. Each has a documented fix.
Permission denied (EACCES) on /home/node/.openclaw. The image runs as the node user, uid 1000. Your host directories must be owned by that uid:
sudo chown -R 1000:1000 /path/to/openclaw-config /path/to/openclaw-workspace
We cover the same error on a normal install in OpenClaw EACCES: permission denied.
“Unauthorized” or “pairing required” in the Control UI. Get a fresh dashboard link, then approve the browser as a device:
docker compose run --rm openclaw-cli dashboard --no-open
docker compose run --rm openclaw-cli devices list
docker compose run --rm openclaw-cli devices approve <requestId>
The CLI targets ws://172.x.x.x or shows pairing errors. Reset the gateway mode and bind, then point the CLI at loopback:
docker compose run --rm openclaw-cli config set --batch-json '[{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"lan"}]'
docker compose run --rm openclaw-cli devices list --url ws://127.0.0.1:18789
A gateway that refuses to start because gateway.mode is unset has its own guide: gateway start blocked by a missing gateway mode.
The image build exits with code 137. The build ran out of memory. Use a host with at least 6 GB of RAM, or skip the build with a pre-built image via OPENCLAW_IMAGE.
Environment changes do not take effect. docker compose restart keeps the old values. Run docker compose up -d after changing environment variables, as our OpenClaw and Ollama guide explains for local models.
Updating OpenClaw in Docker
To update OpenClaw in Docker, pull the new source, rebuild the image and recreate the gateway container. Your config and workspace are untouched because they live in the host bind mounts.
git pull
docker compose build
docker compose up -d
If you run the published image, change or re-pull the image tag instead of building. On a server, pin the version tag, test the new one in a separate throwaway install, and only then move the server to it. A newer version can reject a config key the old one accepted, so run the gateway’s own checks after each update.
Docker Gateway vs Agent Sandbox
Running the gateway in Docker and sandboxing the agent’s tools are two separate features, and the sandbox does not need a containerized gateway. With the sandbox on, the gateway runs agent tool calls such as shell commands and file writes inside isolated Docker containers, while the gateway itself can stay on the host.
The sandbox is configured under agents.defaults.sandbox:
{
agents: {
defaults: {
sandbox: {
mode: "non-main", // off | non-main | all
scope: "agent", // session | agent | shared
},
},
},
}
Build the default sandbox image with scripts/sandbox-setup.sh. To use the sandbox with a Docker gateway, set OPENCLAW_SANDBOX=1 before running the setup script; it mounts the Docker socket only after the sandbox checks pass, and turns the sandbox off again if they fail.
Choose based on what you are protecting. A Docker gateway protects the host from the gateway’s dependencies, while the sandbox protects the host, and other sessions, from what an agent decides to run. If agents will run code for other people, you want the sandbox either way.
Running OpenClaw in Production
A Docker install gets OpenClaw running. Keeping it reliable takes more: watching the gateway, backing up the config directory, testing updates before they reach the live install, and deciding which agent actions need a person’s approval. At Kaxo, we run AI agents in our own business every day, and that is the work that decides whether they stay useful.
If you want to compare hosted, self-hosted and consulting-led options, see our OpenClaw deployment services comparison. If you would rather have someone build and run the agents for you, the Kaxo AI agent development team can help. Book a call and tell us what you want OpenClaw to do.
Frequently Asked Questions
Is there an official OpenClaw Docker image?
Yes. OpenClaw publishes pre-built images on the GitHub Container Registry at ghcr.io/openclaw/openclaw, with tags such as latest, main and specific version numbers. You can also build the image locally from the repository, which is what the setup script does unless you set OPENCLAW_IMAGE.
Do I need Docker to run OpenClaw?
No, OpenClaw's own documentation calls Docker optional. On your own machine the normal npm install gives a faster development loop. Docker is worth it when you want an isolated gateway, a throwaway test environment, or a server where you do not want Node installed on the host.
Where does OpenClaw store data in Docker?
In the bind-mounted config directory, which maps to /home/node/.openclaw inside the container. It holds openclaw.json, the .env file with the gateway token, per-agent auth profiles and the workspace. Anything installed inside the container at runtime is lost when the container is replaced.
Why can't I open the OpenClaw Control UI from Docker?
Usually the gateway is bound to loopback, which keeps it inside the container's network. The Docker setup defaults to the lan bind so the published port 18789 is reachable from the host. Set gateway.bind to lan, not to an address such as 0.0.0.0, then open http://127.0.0.1:18789/.
How do I update OpenClaw running in Docker?
Pull the latest source, rebuild the image and restart the gateway with docker compose build followed by docker compose up -d. If you use a pre-built image, pull the new tag instead of building. Your config and workspace survive because they live in the host bind mounts, not in the container.
Stop Googling OpenClaw errors.
Your agents message ours on Telegram. Production-tested OpenClaw fixes. $99/mo.
