OpenClaw can be deployed with Docker Compose so that the gateway, optional CLI, and optional web search backend run as separate containers but share the same persistent data directory.
What This Setup Does
This deployment defines four services:
openclaw-gateway: the main OpenClaw servicesocat-proxy: exposes the internal gateway port for external accessopenclaw-cli: an on-demand CLI container using the same OpenClaw statesearxng: an optional self-hosted metasearch backend
The persistent data is stored under /home/jerry/openclaw.
Prerequisites
- Docker and Docker Compose plugin installed
- A writable host directory such as
/home/jerry/openclaw - A
.envfile containing the environment variables required by OpenClaw
Check Docker first:
docker --version
docker compose versionPrepare Directories
Create the directories used by the containers:
mkdir -p /home/jerry/openclaw/workspace
mkdir -p /home/jerry/openclaw/searxngThese mounts are used as follows:
/home/jerry/openclaw: OpenClaw configuration and state/home/jerry/openclaw/workspace: working files created by OpenClaw/home/jerry/openclaw/searxng: SearXNG configuration
Compose File
Save the following as docker-compose.yml:
services:
openclaw-gateway:
image: ghcr.io/phioranex/openclaw-docker:latest
container_name: openclaw-gateway
restart: unless-stopped
stdin_open: true
tty: true
# Uncomment the following line if running on Synology NAS or other systems with UID/GID issues
user: "9003:1003"
volumes:
- /home/jerry/openclaw:/home/node/.openclaw
- /home/jerry/openclaw/workspace:/home/node/.openclaw/workspace
- /etc/localtime:/etc/localtime:ro
ports:
- "18789:18789"
- "18790:18790"
environment:
- HOME=/home/node
- NODE_ENV=production
- OPENCLAW_SKIP_SERVICE_CHECK=true
- TZ=Asia/Singapore
env_file:
- .env
command: ["gateway"]
socat-proxy:
image: alpine/socat
container_name: openclaw-socat
restart: unless-stopped
network_mode: "service:openclaw-gateway"
command: "TCP-LISTEN:18790,fork,bind=0.0.0.0,reuseaddr TCP:127.0.0.1:18789"
openclaw-cli:
image: ghcr.io/phioranex/openclaw-docker:latest
container_name: openclaw-cli
stdin_open: true
tty: true
# Uncomment the following line if running on Synology NAS or other systems with UID/GID issues
user: "9003:1003"
volumes:
- /home/jerry/openclaw:/home/node/.openclaw
- /home/jerry/openclaw/workspace:/home/node/.openclaw/workspace
environment:
- HOME=/home/node
- NODE_ENV=production
entrypoint: ["node", "/app/dist/index.js"]
profiles:
- cli
searxng:
image: searxng/searxng:latest
container_name: searxng
ports:
- "8081:8081"
volumes:
- /home/jerry/openclaw/searxng:/etc/searxng
environment:
- SEARXNG_BASE_URL=http://localhost:8081/
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
- DAC_OVERRIDE
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "1"Note
The compose example keeps
user: "9003:1003"enabled. Change it to your own host UID:GID, or remove it entirely if you do not need explicit user mapping.
Environment File
Create a .env file in the same directory as docker-compose.yml.
touch .envPut the OpenClaw-specific secrets and runtime configuration in this file. Do not commit .env into Git.
Add a Telegram Bot
Telegram is one of the simplest ways to access OpenClaw remotely.
1. Create a bot with BotFather
In Telegram, open @BotFather and create a new bot:
/newbotBotFather will return a bot token in the form:
1234567890:ABCdefGHIjklMNOpqrsTUVwxyzKeep this token private.
2. Add the bot token to .env
Add the Telegram token to your .env file:
TELEGRAM_BOT_TOKEN=1234567890:ABCdefGHIjklMNOpqrsTUVwxyzAccording to the OpenClaw Telegram docs, TELEGRAM_BOT_TOKEN works as the environment-variable fallback for the default account.
3. Optional: add Telegram channel config
If you want explicit Telegram channel settings instead of relying only on the environment variable, add a Telegram section in your OpenClaw config under the mounted OpenClaw data directory.
Example:
{
"channels": {
"telegram": {
"enabled": true,
"botToken": "1234567890:ABCdefGHIjklMNOpqrsTUVwxyz",
"dmPolicy": "pairing",
"groups": {
"*": {
"requireMention": true
}
}
}
}
}Recommended defaults:
dmPolicy: "pairing"so random users cannot immediately access the botrequireMention: truein groups so the bot only responds when explicitly mentioned
4. Restart the gateway
After updating .env or the OpenClaw config, restart the containers:
docker compose up -d
docker compose logs -f openclaw-gateway5. Pair your Telegram account
After the gateway is running, send a direct message to your bot in Telegram.
Then use the CLI container to list pending Telegram pairing requests:
docker compose run --rm --profile cli openclaw-cli pairing list telegramApprove the pairing code:
docker compose run --rm --profile cli openclaw-cli pairing approve telegram <CODE>This is the safest default setup for personal use.
6. Optional: use the bot in group chats
If you want the bot to work in a Telegram group:
- add the bot to the group
- keep
requireMention: trueunless you really want it replying to all messages - if the bot needs to read all group messages, disable BotFather privacy mode with
/setprivacyor make the bot a group admin
If you change privacy mode, remove and re-add the bot to the group so Telegram applies the new behavior.
Start the Services
Launch the gateway and SearXNG in the background:
docker compose up -dCheck status:
docker compose ps
docker compose logs -f openclaw-gatewayAccess and Verify
After startup, the main exposed ports are:
18789: OpenClaw gateway18790: forwarded bysocat-proxy8081: SearXNG
Verify the containers are running:
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"If the gateway does not start, check:
- the
.envfile exists and is complete - the mounted directories are writable
- the
user: "9003:1003"mapping matches your host permissions, or remove it and retry
Run the CLI Container
The CLI service is in the cli profile, so it does not start by default.
Run it when needed:
docker compose run --rm --profile cli openclaw-cli --helpBecause the CLI shares /home/node/.openclaw, it uses the same configuration and workspace as the gateway container.
Update the Deployment
Pull the latest images and recreate the services:
docker compose pull
docker compose up -dStop or Remove
Stop the stack:
docker compose stopRemove containers while keeping data:
docker compose downNotes
- Keep
/home/jerry/openclawbacked up if the workspace or configuration matters. searxngis optional. Remove that service if you do not need a local search backend.- If this is exposed outside your local machine, put it behind a reverse proxy and access control instead of publishing the ports directly.
- Telegram references:
Related Tools
- AI Tools - Return to the AI tools overview
- Claude Code - Terminal-based coding assistant workflow
- Docker - General Docker usage notes