Home About Who We Are Team Services Startups Businesses Enterprise Case Studies Blog Guides Contact Connect with Us
Back to Guides
Software & Platforms 13 min read

Openclaw Docker Deployment: Containerized Agent Setup Guide

Openclaw Docker Deployment: Containerized Agent Setup Guide

Docker Compose accounts for roughly 65% of all Openclaw deployments, and there is a good reason for it: you get process isolation, reproducible builds, and one-command updates without touching your host system. But the default docker-setup.sh script produces a minimal configuration that skips resource limits, log rotation, and proper restart policies. In production, that catches up with you fast.

This guide gives you a complete, copy-paste-ready Docker Compose setup for Openclaw with health checks, volume persistence, security hardening, and auto-restart baked in. The configuration below reflects production best practices rather than what the quickstart docs suggest.

Prerequisites

Before starting, confirm you have the following installed on your host machine:

  • Docker Engine 24+ or Docker Desktop
  • Docker Compose v2 (the docker compose plugin, not the legacy docker-compose binary)
  • Git for cloning the Openclaw repository
  • Minimum 2 GB RAM available for the container (the build process OOM-kills on 1 GB hosts with exit code 137)
  • An API key from your LLM provider (OpenAI, Anthropic, or OpenRouter)

Verify your Docker installation:

docker --version
docker compose version

If you need Docker installed from scratch on Ubuntu, the full process takes about two minutes:

sudo apt update && sudo apt install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

If you have not set up Openclaw at all yet, start with our Openclaw setup guide to understand the workspace files, memory system, and model selection before containerizing.

Clone and Run the Setup Script

Start by cloning the Openclaw repository and running the automated setup:

git clone https://github.com/openclaw/openclaw.git
cd openclaw
./scripts/docker/setup.sh

The script walks you through several prompts: gateway mode (choose local), LLM provider selection, and API key entry. It generates a .env file with your gateway token and fires up the containers via Docker Compose.

To use a pre-built image instead of building locally (faster, skips the 2 GB RAM build requirement):

export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
./scripts/docker/setup.sh

Pre-built images are tagged at GitHub Container Registry as latest, main, or version-specific like 2026.2.26.

The Production Docker Compose File

The default docker-compose.yml from the repository works, but it lacks resource constraints, health check intervals, restart policies, and log management. Here is a production-hardened version you can use as a drop-in replacement:

version: "3.8"

services:
  openclaw-gateway:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw-gateway
    env_file: .env
    ports:
      - "18789:18789"
    volumes:
      - ${OPENCLAW_CONFIG_DIR:-~/.openclaw}:/home/node/.openclaw
      - ${OPENCLAW_WORKSPACE_DIR:-~/openclaw/workspace}:/home/node/.openclaw/workspace
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:18789/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: "2.0"
        reservations:
          memory: 2G
          cpus: "1.0"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "5"
    security_opt:
      - no-new-privileges:true

What each addition does and why it matters:

  • restart: unless-stopped keeps the container running through host reboots and crash loops. The only way it stays down is if you explicitly stop it.
  • healthcheck pings the /healthz liveness endpoint every 30 seconds. After 3 consecutive failures, Docker marks the container as unhealthy. Orchestrators like Watchtower or Docker Swarm can auto-restart unhealthy containers.
  • deploy.resources caps the container at 4 GB RAM and 2 CPU cores while reserving a floor of 2 GB and 1 core. This prevents Openclaw from starving other services on shared hosts.
  • logging rotates JSON log files at 50 MB with 5 files max. Without this, Openclaw logs grow unbounded and will fill your disk within weeks on an active instance.
  • security_opt: no-new-privileges prevents the container process from gaining additional privileges through setuid binaries. A baseline security measure for any production container.

Environment Variables

Create a .env file in the same directory as your docker-compose.yml. The setup script generates most of these, but here is the complete reference:

# Required
OPENCLAW_GATEWAY_TOKEN=your_generated_token_here
LLM_PROVIDER=openai
OPENAI_API_KEY=sk-your-api-key-here

# Optional: use Anthropic instead
# LLM_PROVIDER=anthropic
# ANTHROPIC_API_KEY=sk-ant-your-key-here

# Volume paths (defaults shown)
OPENCLAW_CONFIG_DIR=~/.openclaw
OPENCLAW_WORKSPACE_DIR=~/openclaw/workspace

# Network binding
OPENCLAW_GATEWAY_BIND=lan

# Optional: pre-built image tag
OPENCLAW_IMAGE=ghcr.io/openclaw/openclaw:latest

# Optional: extra apt packages for the container
# OPENCLAW_DOCKER_APT_PACKAGES=ripgrep jq

# Optional: enable sandboxed tool execution
# OPENCLAW_SANDBOX=true

Lock down the file permissions immediately:

chmod 600 .env

Never commit .env to version control. Add it to your .gitignore if you are tracking your deployment configuration in Git.

Volume Mounts and Persistence

Docker Compose bind-mounts two host directories into the container:

Host PathContainer PathContents
~/.openclaw/home/node/.openclawConfiguration, memory files, API keys, channel configs
~/openclaw/workspace/home/node/.openclaw/workspaceWorkspace files (agents.md, soul.md, heartbeat.md, skills)

These directories survive container replacement. When you pull a new image and recreate the container, all your configuration, memory, and workspace files persist.

The uid 1000 Gotcha

The Openclaw container runs as user node with uid 1000. If your host directories are owned by a different user, the container cannot write to them. This is the single most common cause of “permission denied” errors after a fresh Docker deployment.

Fix it before you start:

sudo chown -R 1000:1000 ~/.openclaw ~/openclaw/workspace

Watch for Disk Growth

Active Openclaw instances generate files that accumulate over time:

  • media/ stores downloaded files and browser screenshots
  • Session JSONL files log every conversation turn
  • cron/runs/ logs scheduled task executions
  • /tmp/openclaw/ holds temporary processing files

On a moderately active instance, expect 500 MB to 1 GB of growth per month. Set a calendar reminder to check disk usage monthly, or add a monitoring alert at 80% capacity.

Health Checks and Monitoring

Openclaw exposes two unauthenticated probe endpoints:

# Liveness: is the process running?
curl -fsS http://127.0.0.1:18789/healthz

# Readiness: is the gateway accepting requests?
curl -fsS http://127.0.0.1:18789/readyz

For deeper inspection (requires your gateway token):

docker compose exec openclaw-gateway \
  node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN"

The healthcheck directive in the docker-compose.yml above uses the liveness endpoint. If you are running behind a reverse proxy like Nginx or Traefik, point your upstream health check at /readyz instead, since readiness confirms the gateway is ready to process requests, not just alive.

Docker vs Bare Metal vs systemd

Not every deployment needs Docker. Here is when each approach makes sense:

FactorDocker ComposeBare Metal (npm)systemd Service
Setup complexityMediumLowMedium
Process isolationStrong (container boundary)NoneProcess-level only
Resource limitsBuilt-in (cgroups)Manual (ulimit)Manual (cgroups via unit file)
Update processdocker compose pull && up -dgit pull && npm installgit pull && systemctl restart
RollbackInstant (pin image tag)Manual (git revert)Manual (git revert)
Multi-instanceTrivial (one compose file per instance)Separate directoriesSeparate unit files
Log managementBuilt-in rotationManualjournald (built-in)
Host contaminationNoneNode.js + deps on hostNode.js + deps on host
RAM overhead~100-200 MB extraBaselineBaseline

Use Docker when you want isolation, run multiple Openclaw instances on one host, or need reproducible deployments across machines. Docker is the right choice for most DevOps teams.

Use bare metal when you are on a resource-constrained VPS with exactly 2 GB RAM and cannot spare the container overhead. Install Openclaw directly with npm and manage it with pm2 or a systemd unit.

Use systemd when you want a single persistent instance on a dedicated Linux server without the Docker layer. Systemd handles restarts natively and integrates with journald for logging. The enterprise deployment guide covers the systemd approach for small teams.

Docker Compose is the best default for anything beyond a quick personal test. The isolation alone prevents the “it works on my machine” problem when you move from local development to a VPS.

Connecting Messaging Channels

After the gateway is running, add your messaging integrations:

# Telegram (most common)
docker compose run --rm openclaw-cli channels add \
  --channel telegram --token "YOUR_BOT_TOKEN"

# WhatsApp (QR code flow)
docker compose run --rm openclaw-cli channels login

# Discord
docker compose run --rm openclaw-cli channels add \
  --channel discord --token "YOUR_DISCORD_TOKEN"

# Slack
docker compose run --rm openclaw-cli channels add \
  --channel slack --token "YOUR_SLACK_TOKEN"

Create your Telegram bot via @BotFather first. If you need Slack integration specifically, our Slack to Openclaw guide covers the full OAuth setup.

Updating Your Deployment

Pull the latest image and recreate the container in one sequence:

docker compose pull
docker compose up -d
docker image prune -f

Your volumes are bind-mounted, so configuration and workspace files are untouched. The prune command cleans up old image layers to reclaim disk space.

To pin a specific version instead of tracking latest:

image: ghcr.io/openclaw/openclaw:2026.3.15

Version pinning is worth the minor inconvenience if you run Openclaw in production. A breaking change in latest at 2 AM is not how you want to discover an incompatibility.

Securing Your Docker Deployment

Beyond no-new-privileges in the compose file, apply these hardening steps for any internet-facing deployment:

Firewall rules to restrict access:

sudo ufw allow 22/tcp
sudo ufw allow 18789/tcp
sudo ufw enable

Better yet, restrict port 18789 to your IP or VPN only:

sudo ufw allow from YOUR_IP to any port 18789

Reverse proxy with TLS using Nginx, Traefik, or Caddy. Never expose the gateway port directly over HTTP in production. A minimal Caddy config:

openclaw.yourdomain.com {
    reverse_proxy localhost:18789
}

Caddy handles automatic HTTPS via Let’s Encrypt, which is one less thing to manage.

Drop all capabilities if you do not need Openclaw to execute shell commands on the host:

security_opt:
  - no-new-privileges:true
cap_drop:
  - ALL

This is the most restrictive configuration. If Openclaw needs to run shell tools, you will need to selectively add capabilities back.

Troubleshooting Docker-Specific Issues

Container exits immediately with code 137

This is an out-of-memory kill. Your host has less than 2 GB RAM available for the container. Either upgrade the host or use a pre-built image (which skips the memory-intensive build step):

export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"

Permission denied on mounted volumes

The container runs as uid 1000. Fix ownership:

sudo chown -R 1000:1000 ~/.openclaw ~/openclaw/workspace

Port 18789 already in use

Another process is using the port. Find and stop it, or remap Openclaw to a different host port:

ports:
  - "18790:18789"

Container is unhealthy but running

The health check is failing. Check the gateway logs:

docker compose logs --tail 50 openclaw-gateway

Common causes: the gateway has not finished starting (increase start_period in the health check), or the LLM provider API key is invalid.

Pairing requests not appearing

If Telegram or other channels show “pairing required,” list and approve pending devices:

docker compose run --rm openclaw-cli devices list
docker compose run --rm openclaw-cli devices approve REQUEST_ID

Frequently Asked Questions

Does Openclaw support Docker on ARM (Apple Silicon, Raspberry Pi)?

The official images are built for amd64. On ARM hosts, Docker builds from source using emulation, which is slow but works. For Apple Silicon Macs, Docker Desktop handles the translation transparently. Raspberry Pi 4 with 4 GB RAM can run Openclaw, but expect slower response times due to emulation overhead.

How much RAM does a running Openclaw container use?

A baseline idle instance uses around 400-600 MB. Active sessions with browser automation push that to 1-2 GB. The 4 GB limit in the production compose file above accounts for memory spikes during tool execution, which are unpredictable. If you are running multiple instances on one host, budget 2 GB per instance minimum.

Can I run multiple Openclaw instances on one machine?

Yes. Duplicate the docker-compose.yml, change the container name and host port, and point the volume mounts to separate directories. Each instance gets isolated config, workspace, and memory. The enterprise deployment guide covers multi-instance architecture in detail.

Should I use Docker volumes or bind mounts?

Bind mounts (what we use in this guide) are simpler for Openclaw because you can directly access the workspace files from your host for editing and backup. Named Docker volumes provide better isolation but make it harder to inspect and back up your configuration files. For most teams, bind mounts are the right choice.

How do I back up my Openclaw Docker deployment?

Back up the two bind-mounted directories: ~/.openclaw (config, memory, keys) and ~/openclaw/workspace (workspace files, skills). A cron job running tar works for simple setups:

tar -czf /backups/openclaw-$(date +%F).tar.gz ~/.openclaw ~/openclaw/workspace

For automated backups, point a tool like restic or borgbackup at those directories.

What happens to my data when I update the container?

Nothing. Your configuration and workspace live in bind-mounted host directories, not inside the container. Pulling a new image and recreating the container leaves all your data intact. This is one of the key advantages of the volume mount approach.

Key Takeaways

  • Use the production docker-compose.yml from this guide instead of the default. It adds health checks, resource limits, log rotation, and restart policies that the quickstart skips.
  • Fix uid 1000 ownership on your volume directories before first start. This is the number one cause of Docker-specific Openclaw failures.
  • Pin your image tag in production rather than tracking latest. Breaking changes at unexpected times are not worth the convenience.
  • Set up log rotation from day one. An active Openclaw instance generates substantial log volume, and Docker’s default is to keep everything forever.
  • Docker Compose is the right deployment method for most teams. Only drop to bare metal if you are genuinely RAM-constrained, and only move to Kubernetes if you need to manage dozens of instances across regions.

Last Updated: Apr 17, 2026

SL

SFAI Labs

SFAI Labs helps companies build AI-powered products that work. We focus on practical solutions, not hype.

Need Help Setting Up OpenClaw?

  • VPS deployment, SSL, and security hardening done for you
  • Integration configuration — connect your tools on day one
  • Custom skill development for your specific workflows
Get OpenClaw Setup Help →
No commitment · Free consultation

Related articles