2026-01-02 20:58:50 +01:00
---
2026-01-31 21:13:13 +09:00
summary: "Optional Docker-based setup and onboarding for OpenClaw"
2026-01-02 20:58:50 +01:00
read_when:
- You want a containerized gateway instead of local installs
- You are validating the Docker flow
2026-01-31 16:04:03 -05:00
title: "Docker"
2026-01-02 20:58:50 +01:00
---
# Docker (optional)
Docker is **optional ** . Use it only if you want a containerized gateway or to validate the Docker flow.
2026-01-08 21:56:41 +01:00
## Is Docker right for me?
2026-01-30 03:15:10 +01:00
- **Yes**: you want an isolated, throwaway gateway environment or to run OpenClaw on a host without local installs.
2026-03-19 12:07:37 -07:00
- **No**: you are running on your own machine and just want the fastest dev loop. Use the normal install flow instead.
2026-01-08 21:56:41 +01:00
- **Sandboxing note**: agent sandboxing uses Docker too, but it does **not ** require the full gateway to run in Docker. See [Sandboxing ](/gateway/sandboxing ).
2026-03-19 12:07:37 -07:00
## Prerequisites
2026-01-03 21:35:44 +01:00
- Docker Desktop (or Docker Engine) + Docker Compose v2
2026-02-25 08:35:48 +01:00
- At least 2 GB RAM for image build (`pnpm install` may be OOM-killed on 1 GB hosts with exit 137)
2026-03-19 12:07:37 -07:00
- Enough disk for images and logs
2026-03-03 23:28:35 +03:00
- If running on a VPS/public host, review
2026-03-22 15:50:49 -07:00
[Security hardening for network exposure ](/gateway/security ),
2026-03-03 23:28:35 +03:00
especially Docker `DOCKER-USER` firewall policy.
2026-01-03 21:35:44 +01:00
2026-03-19 12:07:37 -07:00
## Containerized Gateway
2026-01-11 03:27:48 +01:00
2026-03-19 12:07:37 -07:00
<Steps>
<Step title="Build the image">
From the repo root, run the setup script:
2026-01-31 18:31:49 +09:00
2026-03-19 12:07:37 -07:00
```bash
2026-03-19 13:40:10 -07:00
./scripts/docker/setup.sh
2026-03-19 12:07:37 -07:00
` ``
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
This builds the gateway image locally. To use a pre-built image instead:
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
` ``bash
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
2026-03-19 13:40:10 -07:00
./scripts/docker/setup.sh
2026-03-19 12:07:37 -07:00
` ``
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
Pre-built images are published at the
[GitHub Container Registry](https://github.com/openclaw/openclaw/pkgs/container/openclaw).
Common tags: ` main`, ` latest`, ` <version>` (e.g. ` 2026.2.26`).
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
</Step>
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
<Step title="Complete onboarding">
The setup script runs onboarding automatically. It will:
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
- prompt for provider API keys
- generate a gateway token and write it to ` .env`
- start the gateway via Docker Compose
2026-01-31 18:31:49 +09:00
2026-03-24 16:44:47 -07:00
During setup, pre-start onboarding and config writes run through
` openclaw-gateway` directly. ` openclaw-cli` is for commands you run after
the gateway container already exists.
2026-03-19 12:07:37 -07:00
</Step>
2026-01-02 20:58:50 +01:00
2026-03-19 12:07:37 -07:00
<Step title="Open the Control UI">
2026-04-04 21:04:17 +01:00
Open ` http://127.0.0.1:18789/` in your browser and paste the configured
shared secret into Settings. The setup script writes a token to ` .env` by
default; if you switch the container config to password auth, use that
password instead.
2026-01-09 18:21:28 +01:00
2026-03-19 12:07:37 -07:00
Need the URL again?
2026-03-01 18:31:20 -08:00
2026-03-19 12:07:37 -07:00
` ``bash
docker compose run --rm openclaw-cli dashboard --no-open
` ``
2026-03-01 18:31:20 -08:00
2026-03-19 12:07:37 -07:00
</Step>
2026-03-01 18:31:20 -08:00
2026-03-19 12:07:37 -07:00
<Step title="Configure channels (optional)">
Use the CLI container to add messaging channels:
2026-03-01 18:31:20 -08:00
2026-03-19 12:07:37 -07:00
` ``bash
# WhatsApp (QR)
docker compose run --rm openclaw-cli channels login
2026-03-01 18:31:20 -08:00
2026-03-19 12:07:37 -07:00
# Telegram
docker compose run --rm openclaw-cli channels add --channel telegram --token "<token>"
2026-03-01 18:31:20 -08:00
2026-03-19 12:07:37 -07:00
# Discord
docker compose run --rm openclaw-cli channels add --channel discord --token "<token>"
` ``
2026-03-01 19:22:44 -08:00
2026-03-19 12:07:37 -07:00
Docs: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord](/channels/discord)
2026-03-01 19:22:44 -08:00
2026-03-19 12:07:37 -07:00
</Step>
</Steps>
2026-03-01 19:22:44 -08:00
2026-03-19 12:07:37 -07:00
### Manual flow
2026-03-01 19:22:44 -08:00
2026-03-19 12:07:37 -07:00
If you prefer to run each step yourself instead of using the setup script:
2026-01-02 20:58:50 +01:00
` ``bash
2026-01-30 03:15:10 +01:00
docker build -t openclaw:local -f Dockerfile .
2026-03-24 16:44:47 -07:00
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 \
2026-04-05 22:26:59 +01:00
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"]}]'
2026-01-30 03:15:10 +01:00
docker compose up -d openclaw-gateway
2026-01-02 20:58:50 +01:00
` ``
2026-03-19 12:07:37 -07:00
<Note>
Run ` docker compose` from the repo root. If you enabled ` OPENCLAW_EXTRA_MOUNTS`
or ` OPENCLAW_HOME_VOLUME`, the setup script writes ` docker-compose.extra.yml`;
include it with ` -f docker-compose.yml -f docker-compose.extra.yml`.
</Note>
2026-01-08 07:48:23 +00:00
2026-03-24 16:44:47 -07:00
<Note>
Because ` openclaw-cli` shares ` openclaw-gateway`'s network namespace, it is a
post-start tool. Before ` docker compose up -d openclaw-gateway`, run onboarding
and setup-time config writes through ` openclaw-gateway` with
` --no-deps --entrypoint node`.
</Note>
2026-03-19 12:07:37 -07:00
### Environment variables
2026-01-08 07:48:23 +00:00
2026-03-19 12:07:37 -07:00
The setup script accepts these optional environment variables:
2026-02-02 04:25:57 -08:00
2026-03-19 12:07:37 -07:00
| Variable | Purpose |
| ------------------------------ | ---------------------------------------------------------------- |
| ` OPENCLAW_IMAGE` | Use a remote image instead of building locally |
| ` OPENCLAW_DOCKER_APT_PACKAGES` | Install extra apt packages during build (space-separated) |
| ` OPENCLAW_EXTENSIONS` | Pre-install extension deps at build time (space-separated names) |
| ` OPENCLAW_EXTRA_MOUNTS` | Extra host bind mounts (comma-separated ` source:target[:opts]`) |
| ` OPENCLAW_HOME_VOLUME` | Persist ` /home/node` in a named Docker volume |
| ` OPENCLAW_SANDBOX` | Opt in to sandbox bootstrap (` 1`, ` true`, ` yes`, ` on`) |
| ` OPENCLAW_DOCKER_SOCKET` | Override Docker socket path |
2026-02-02 04:25:57 -08:00
2026-03-01 20:36:58 -08:00
### Health checks
Container probe endpoints (no auth required):
` ``bash
2026-03-19 12:07:37 -07:00
curl -fsS http://127.0.0.1:18789/healthz # liveness
curl -fsS http://127.0.0.1:18789/readyz # readiness
2026-03-01 20:36:58 -08:00
` ``
2026-03-19 12:07:37 -07:00
The Docker image includes a built-in ` HEALTHCHECK` that pings ` /healthz`.
If checks keep failing, Docker marks the container as ` unhealthy` and
orchestration systems can restart or replace it.
2026-03-01 20:36:58 -08:00
2026-03-19 12:07:37 -07:00
Authenticated deep health snapshot:
2026-01-03 21:35:44 +01:00
` ``bash
2026-01-31 18:31:49 +09:00
docker compose exec openclaw-gateway node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN"
2026-01-03 21:35:44 +01:00
` ``
2026-03-19 12:07:37 -07:00
### LAN vs loopback
2026-03-02 08:28:35 +07:00
2026-03-19 13:40:10 -07:00
` scripts/docker/setup.sh` defaults ` OPENCLAW_GATEWAY_BIND=lan` so host access to
2026-03-02 08:28:35 +07:00
` http://127.0.0.1:18789` works with Docker port publishing.
2026-03-19 12:07:37 -07:00
- ` lan` (default): host browser and host CLI can reach the published gateway port.
2026-03-02 08:28:35 +07:00
- ` loopback`: only processes inside the container network namespace can reach
2026-03-19 12:07:37 -07:00
the gateway directly.
2026-01-03 21:35:44 +01:00
2026-03-19 12:07:37 -07:00
<Note>
Use bind mode values in ` gateway.bind` (` lan` / ` loopback` / ` custom` /
` tailnet` / ` auto`), not host aliases like ` 0.0.0.0` or ` 127.0.0.1`.
</Note>
2026-01-31 18:31:49 +09:00
2026-03-19 12:07:37 -07:00
### Storage and persistence
2026-01-04 16:02:28 +00:00
2026-03-19 12:07:37 -07:00
Docker Compose bind-mounts ` OPENCLAW_CONFIG_DIR` to ` /home/node/.openclaw` and
` OPENCLAW_WORKSPACE_DIR` to ` /home/node/.openclaw/workspace`, so those paths
survive container replacement.
2026-01-04 16:02:28 +00:00
2026-04-04 10:36:35 +01:00
That mounted config directory is where OpenClaw keeps:
- ` openclaw.json` for behavior config
2026-04-04 10:40:40 +01:00
- ` agents/<agentId>/agent/auth-profiles.json` for stored provider OAuth/API-key auth
2026-04-04 10:36:35 +01:00
- ` .env` for env-backed runtime secrets such as ` OPENCLAW_GATEWAY_TOKEN`
2026-03-19 12:07:37 -07:00
For full persistence details on VM deployments, see
[Docker VM Runtime - What persists where](/install/docker-vm-runtime#what-persists-where).
2026-01-04 16:02:28 +00:00
2026-03-19 12:07:37 -07:00
**Disk growth hotspots:** watch ` media/`, session JSONL files, ` cron/runs/*.jsonl`,
and rolling file logs under ` /tmp/openclaw/`.
2026-01-04 16:02:28 +00:00
2026-03-19 12:07:37 -07:00
### Shell helpers (optional)
2026-01-03 22:11:43 +01:00
2026-03-19 12:07:37 -07:00
For easier day-to-day Docker management, install ` ClawDock`:
2026-01-03 22:11:43 +01:00
` ``bash
2026-03-29 17:05:41 -07:00
mkdir -p ~/.clawdock && curl -sL https://raw.githubusercontent.com/openclaw/openclaw/main/scripts/clawdock/clawdock-helpers.sh -o ~/.clawdock/clawdock-helpers.sh
2026-03-19 12:07:37 -07:00
echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc && source ~/.zshrc
2026-01-03 22:11:43 +01:00
` ``
2026-03-29 17:05:41 -07:00
If you installed ClawDock from the older ` scripts/shell-helpers/clawdock-helpers.sh` raw path, rerun the install command above so your local helper file tracks the new location.
2026-03-19 12:07:37 -07:00
Then use ` clawdock-start`, ` clawdock-stop`, ` clawdock-dashboard`, etc. Run
` clawdock-help` for all commands.
2026-03-29 17:05:41 -07:00
See [ClawDock](/install/clawdock) for the full helper guide.
2026-03-19 12:07:37 -07:00
<AccordionGroup>
<Accordion title="Enable agent sandbox for Docker gateway">
` ``bash
export OPENCLAW_SANDBOX=1
2026-03-19 13:40:10 -07:00
./scripts/docker/setup.sh
2026-03-19 12:07:37 -07:00
` ``
Custom socket path (e.g. rootless Docker):
` ``bash
export OPENCLAW_SANDBOX=1
export OPENCLAW_DOCKER_SOCKET=/run/user/1000/docker.sock
2026-03-19 13:40:10 -07:00
./scripts/docker/setup.sh
2026-03-19 12:07:37 -07:00
` ``
The script mounts ` docker.sock` only after sandbox prerequisites pass. If
sandbox setup cannot complete, the script resets ` agents.defaults.sandbox.mode`
to ` off`.
</Accordion>
<Accordion title="Automation / CI (non-interactive)">
Disable Compose pseudo-TTY allocation with ` -T`:
` ``bash
docker compose run -T --rm openclaw-cli gateway probe
docker compose run -T --rm openclaw-cli devices list --json
` ``
</Accordion>
<Accordion title="Shared-network security note">
` openclaw-cli` uses ` network_mode: "service:openclaw-gateway"` so CLI
commands can reach the gateway over ` 127.0.0.1`. Treat this as a shared
trust boundary. The compose config drops ` NET_RAW`/` NET_ADMIN` and enables
` no-new-privileges` on ` openclaw-cli`.
</Accordion>
<Accordion title="Permissions and EACCES">
The image runs as ` node` (uid 1000). If you see permission errors on
` /home/node/.openclaw`, make sure your host bind mounts are owned by uid 1000:
` ``bash
sudo chown -R 1000:1000 /path/to/openclaw-config /path/to/openclaw-workspace
` ``
</Accordion>
<Accordion title="Faster rebuilds">
Order your Dockerfile so dependency layers are cached. This avoids re-running
` pnpm install` unless lockfiles change:
` ``dockerfile
FROM node:24-bookworm
RUN curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:${PATH}"
RUN corepack enable
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY scripts ./scripts
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
RUN pnpm ui:install
RUN pnpm ui:build
ENV NODE_ENV=production
CMD ["node","dist/index.js"]
` ``
</Accordion>
<Accordion title="Power-user container options">
The default image is security-first and runs as non-root ` node`. For a more
full-featured container:
1. **Persist ` /home/node`**: ` export OPENCLAW_HOME_VOLUME="openclaw_home"`
2. **Bake system deps**: ` export OPENCLAW_DOCKER_APT_PACKAGES="git curl jq"`
3. **Install Playwright browsers**:
` ``bash
docker compose run --rm openclaw-cli \
node /app/node_modules/playwright-core/cli.js install chromium
` ``
4. **Persist browser downloads**: set
` PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright` and use
` OPENCLAW_HOME_VOLUME` or ` OPENCLAW_EXTRA_MOUNTS`.
</Accordion>
<Accordion title="OpenAI Codex OAuth (headless Docker)">
If you pick OpenAI Codex OAuth in the wizard, it opens a browser URL. In
Docker or headless setups, copy the full redirect URL you land on and paste
it back into the wizard to finish auth.
</Accordion>
<Accordion title="Base image metadata">
The main Docker image uses ` node:24-bookworm` and publishes OCI base-image
annotations including ` org.opencontainers.image.base.name`,
` org.opencontainers.image.source`, and others. See
[OCI image annotations](https://github.com/opencontainers/image-spec/blob/main/annotations.md).
</Accordion>
</AccordionGroup>
### Running on a VPS?
See [Hetzner (Docker VPS)](/install/hetzner) and
[Docker VM Runtime](/install/docker-vm-runtime) for shared VM deployment steps
including binary baking, persistence, and updates.
## Agent Sandbox
When ` agents.defaults.sandbox` is enabled, the gateway runs agent tool execution
(shell, file read/write, etc.) inside isolated Docker containers while the
gateway itself stays on the host. This gives you a hard wall around untrusted or
multi-tenant agent sessions without containerizing the entire gateway.
Sandbox scope can be per-agent (default), per-session, or shared. Each scope
gets its own workspace mounted at ` /workspace`. You can also configure
allow/deny tool policies, network isolation, resource limits, and browser
containers.
For full configuration, images, security notes, and multi-agent profiles, see:
- [Sandboxing](/gateway/sandboxing) -- complete sandbox reference
- [OpenShell](/gateway/openshell) -- interactive shell access to sandbox containers
- [Multi-Agent Sandbox and Tools](/tools/multi-agent-sandbox-tools) -- per-agent overrides
### Quick enable
2026-01-03 22:11:43 +01:00
` ``json5
{
2026-01-09 12:44:23 +00:00
agents: {
defaults: {
sandbox: {
2026-03-19 12:07:37 -07:00
mode: "non-main", // off | non-main | all
scope: "agent", // session | agent | shared
2026-01-31 18:31:49 +09:00
},
},
},
2026-01-03 22:11:43 +01:00
}
` ``
2026-03-19 12:07:37 -07:00
Build the default sandbox image:
2026-01-03 21:35:44 +01:00
` ``bash
2026-03-19 12:07:37 -07:00
scripts/sandbox-setup.sh
2026-01-03 21:35:44 +01:00
` ``
## Troubleshooting
2026-03-19 12:07:37 -07:00
<AccordionGroup>
<Accordion title="Image missing or sandbox container not starting">
Build the sandbox image with
[` scripts/sandbox-setup.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/sandbox-setup.sh)
or set ` agents.defaults.sandbox.docker.image` to your custom image.
Containers are auto-created per session on demand.
</Accordion>
<Accordion title="Permission errors in sandbox">
Set ` docker.user` to a UID:GID that matches your mounted workspace ownership,
or chown the workspace folder.
</Accordion>
<Accordion title="Custom tools not found in sandbox">
OpenClaw runs commands with ` sh -lc` (login shell), which sources
` /etc/profile` and may reset PATH. Set ` docker.env.PATH` to prepend your
custom tool paths, or add a script under ` /etc/profile.d/` in your Dockerfile.
</Accordion>
<Accordion title="OOM-killed during image build (exit 137)">
The VM needs at least 2 GB RAM. Use a larger machine class and retry.
</Accordion>
<Accordion title="Unauthorized or pairing required in Control UI">
Fetch a fresh dashboard link and approve the browser device:
` ``bash
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>
` ``
More detail: [Dashboard](/web/dashboard), [Devices](/cli/devices).
</Accordion>
<Accordion title="Gateway target shows ws://172.x.x.x or pairing errors from Docker CLI">
Reset gateway mode and bind:
` ``bash
2026-04-05 22:26:59 +01:00
docker compose run --rm openclaw-cli config set --batch-json '[{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"lan"}]'
2026-03-19 12:07:37 -07:00
docker compose run --rm openclaw-cli devices list --url ws://127.0.0.1:18789
` ``
</Accordion>
</AccordionGroup>
2026-03-31 14:38:46 +09:00
## Related
- [Install Overview ](/install ) — all installation methods
- [Podman ](/install/podman ) — Podman alternative to Docker
- [ClawDock ](/install/clawdock ) — Docker Compose community setup
- [Updating ](/install/updating ) — keeping OpenClaw up to date
- [Configuration ](/gateway/configuration ) — gateway configuration after install