18 KiB
| summary | read_when | title | ||
|---|---|---|---|---|
| Optional Docker-based setup and onboarding for OpenClaw |
|
Docker |
Docker (optional)
Docker is optional. Use it only if you want a containerized gateway or to validate the Docker flow.
Is Docker right for me?
- Yes: you want an isolated, throwaway gateway environment or to run OpenClaw on a host without local installs.
- No: you are running on your own machine and just want the fastest dev loop. Use the normal install flow instead.
- Sandboxing note: agent sandboxing uses Docker too, but it does not require the full gateway to run in Docker. See Sandboxing.
Prerequisites
- Docker Desktop (or Docker Engine) + Docker Compose v2
- At least 2 GB RAM for image build (
pnpm installmay be OOM-killed on 1 GB hosts with exit 137) - Enough disk for images and logs
- If running on a VPS/public host, review
Security hardening for network exposure,
especially Docker
DOCKER-USERfirewall policy.
Containerized Gateway
From the repo root, run the setup script:```bash
./scripts/docker/setup.sh
```
This builds the gateway image locally. To use a pre-built image instead:
```bash
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
./scripts/docker/setup.sh
```
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`).
The setup script runs onboarding automatically. It will:
- prompt for provider API keys
- generate a gateway token and write it to `.env`
- start the gateway via Docker Compose
Open `http://127.0.0.1:18789/` in your browser and paste the token into
Settings.
Need the URL again?
```bash
docker compose run --rm openclaw-cli dashboard --no-open
```
Use the CLI container to add messaging channels:
```bash
# WhatsApp (QR)
docker compose run --rm openclaw-cli channels login
# Telegram
docker compose run --rm openclaw-cli channels add --channel telegram --token "<token>"
# Discord
docker compose run --rm openclaw-cli channels add --channel discord --token "<token>"
```
Docs: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord](/channels/discord)
Manual flow
If you prefer to run each step yourself instead of using the setup script:
docker build -t openclaw:local -f Dockerfile .
docker compose run --rm openclaw-cli onboard
docker compose up -d openclaw-gateway
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`.
Environment variables
The setup script accepts these optional environment variables:
| 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_INSTALL_BROWSER |
Install Chromium and Playwright deps during the image build |
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 |
OPENCLAW_INSTALL_DOCKER_CLI |
Install Docker CLI in the image (auto-set for sandbox bootstrap) |
OPENCLAW_ALLOW_INSECURE_PRIVATE_WS |
Allow trusted private-network ws:// client targets |
OPENCLAW_TZ |
Set container timezone (for example America/Los_Angeles) |
Use a remote image (skip local build)
Use image name ghcr.io/openclaw/openclaw (not similarly named Docker Hub
images).
Common tags:
main— latest build frommain<version>— release tag builds (for example2026.3.12)latest— latest stable release tag
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
./scripts/docker/setup.sh
Extra mounts (optional)
Set OPENCLAW_EXTRA_MOUNTS to add host directories to both containers:
export OPENCLAW_EXTRA_MOUNTS="$HOME/.codex:/home/node/.codex:ro,$HOME/github:/home/node/github:rw"
./scripts/docker/setup.sh
Notes:
- Paths must be shared with Docker Desktop on macOS/Windows.
- Each entry must be
source:target[:options]with no spaces or control characters. - Rerun the setup script after changing the value so
docker-compose.extra.ymlis regenerated.
Persist the entire container home (optional)
Use OPENCLAW_HOME_VOLUME if you want /home/node to survive container
recreation:
export OPENCLAW_HOME_VOLUME="openclaw_home"
./scripts/docker/setup.sh
Install extra apt packages (optional)
OPENCLAW_DOCKER_APT_PACKAGES installs additional Debian packages at build time:
export OPENCLAW_DOCKER_APT_PACKAGES="ffmpeg build-essential"
./scripts/docker/setup.sh
The Docker image already includes a baseline for common container workflows:
cron, gosu, pnpm, non-root npm -g, go install, Linuxbrew, and browser
runtime libraries. Add only the extra packages your environment needs.
Install browser dependencies at build time (optional)
If you want Chromium baked into the image instead of downloading it later:
export OPENCLAW_INSTALL_BROWSER=1
./scripts/docker/setup.sh
This installs Chromium through Playwright during the image build and stores it
under /home/node/.cache/ms-playwright.
Pre-install extension dependencies (optional)
Extensions with their own package.json can be baked into the image:
export OPENCLAW_EXTENSIONS="diagnostics-otel matrix"
./scripts/docker/setup.sh
Keep macOS awake (optional)
Docker itself does not reliably keep macOS awake. If the gateway must stay online for Slack, webhooks, or scheduled jobs:
scripts/openclaw-keepawake.sh on
scripts/openclaw-keepawake.sh status
scripts/openclaw-keepawake.sh off
By default this uses caffeinate -imsu, which allows the displays to sleep.
Set OPENCLAW_KEEPAWAKE_FLAGS=-dimsu if you also want to keep the displays on.
Base image metadata
The main Docker image uses node:24-bookworm and publishes OCI base-image
annotations including:
org.opencontainers.image.base.nameorg.opencontainers.image.base.digestorg.opencontainers.image.sourceorg.opencontainers.image.documentation
Reference: OCI image annotations
Health checks
Container probe endpoints (no auth required):
curl -fsS http://127.0.0.1:18789/healthz # liveness
curl -fsS http://127.0.0.1:18789/readyz # readiness
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.
Authenticated deep health snapshot:
docker compose exec openclaw-gateway node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN"
LAN vs loopback
scripts/docker/setup.sh defaults OPENCLAW_GATEWAY_BIND=lan so host access to
http://127.0.0.1:18789 works with Docker port publishing.
lan(default): host browser and host CLI can reach the published gateway port.loopback: only processes inside the container network namespace can reach the gateway directly.
Storage and persistence
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.
For full persistence details on VM deployments, see Docker VM Runtime - What persists where.
Disk growth hotspots: watch media/, session JSONL files, cron/runs/*.jsonl,
and rolling file logs under /tmp/openclaw/.
Shell helpers (optional)
For easier day-to-day Docker management, install ClawDock:
mkdir -p ~/.clawdock && curl -sL https://raw.githubusercontent.com/openclaw/openclaw/main/scripts/shell-helpers/clawdock-helpers.sh -o ~/.clawdock/clawdock-helpers.sh
echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc && source ~/.zshrc
Then use clawdock-start, clawdock-stop, clawdock-dashboard, etc. Run
clawdock-help for all commands.
See the ClawDock Helper README.
Custom socket path (e.g. rootless Docker):
```bash
export OPENCLAW_SANDBOX=1
export OPENCLAW_DOCKER_SOCKET=/run/user/1000/docker.sock
./scripts/docker/setup.sh
```
The script mounts `docker.sock` only after sandbox prerequisites pass. If
sandbox setup cannot complete, the script resets `agents.defaults.sandbox.mode`
to `off`.
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
```
`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`.
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
```
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"]
```
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`.
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.
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).
Backup and migration (Intel Mac to Apple Silicon)
For low-disruption host migration, move OpenClaw data and config, then rebuild the Docker image natively on the new machine.
Use:
scripts/migrate/backup-openclaw.shon the source hostscripts/migrate/restore-openclaw.shon the target host
1) Create a backup on the source host
From the repo root:
scripts/migrate/backup-openclaw.sh
The archive includes:
- OpenClaw config dir (
OPENCLAW_CONFIG_DIRor~/.openclaw) - OpenClaw workspace dir (
OPENCLAW_WORKSPACE_DIRor~/.openclaw/workspace) .envand Docker setup files from the repo root- metadata and an internal checksum manifest
Output files:
backups/openclaw-backup-<timestamp>.tar.gzbackups/openclaw-backup-<timestamp>.tar.gz.sha256
Optional path overrides:
scripts/migrate/backup-openclaw.sh \
--config-dir "$HOME/.openclaw" \
--workspace-dir "$HOME/.openclaw/workspace" \
--output-dir "$HOME/openclaw-backups"
2) Transfer the archive to the target host
Copy the archive and checksum file to the new machine using your normal secure transfer method.
3) Restore on the target host
From the repo root on the target host:
scripts/migrate/restore-openclaw.sh --archive /path/to/openclaw-backup-<timestamp>.tar.gz
Default restore behavior:
- verifies archive checksums
- stops
openclaw-gatewaybefore restore - snapshots current config and workspace as
.pre-restore-<timestamp> - restores config and workspace from backup
- writes the backup env file as
.env.from-backupfor review
To overwrite .env directly:
scripts/migrate/restore-openclaw.sh \
--archive /path/to/openclaw-backup-<timestamp>.tar.gz \
--apply-env
4) Rebuild and validate on the target architecture
Always rebuild on Apple Silicon:
docker compose up -d --build --force-recreate openclaw-gateway
docker compose run --rm openclaw-cli health
docker compose run --rm openclaw-cli channels status --probe
Architecture migration note
Do not carry over architecture-specific binary caches from x86 to arm hosts. Rebuild containers and reinstall native toolchains on the target host.
Running on a VPS?
See Hetzner (Docker VPS) and 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 -- complete sandbox reference
- OpenShell -- interactive shell access to sandbox containers
- Multi-Agent Sandbox and Tools -- per-agent overrides
Quick enable
{
agents: {
defaults: {
sandbox: {
mode: "non-main", // off | non-main | all
scope: "agent", // session | agent | shared
},
},
},
}
Build the default sandbox image:
scripts/sandbox-setup.sh
Troubleshooting
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. Set `docker.user` to a UID:GID that matches your mounted workspace ownership, or chown the workspace folder. 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. The VM needs at least 2 GB RAM. Use a larger machine class and retry. 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).
Reset gateway mode and bind:
```bash
docker compose run --rm openclaw-cli config set gateway.mode local
docker compose run --rm openclaw-cli config set gateway.bind lan
docker compose run --rm openclaw-cli devices list --url ws://127.0.0.1:18789
```