DEV Community

zac
zac

Posted on • Originally published at remoteopenclaw.com

OpenClaw Docker Compose: Complete Configuration Guide

Originally published on Remote OpenClaw.

OpenClaw Docker Compose: Complete Configuration Guide

Marketplace

Free skills and AI personas for OpenClaw — browse the marketplace.

Browse the Marketplace →

Join the Community

Join 1k+ OpenClaw operators sharing deployment guides, security configs, and workflow automations.

Join the Community →

What Is the Minimum docker-compose.yml?

Here is the simplest working docker-compose.yml for OpenClaw:

version: "3.8"

services:
 openclaw:
 image: openclaw/openclaw:latest
 container_name: openclaw
 restart: unless-stopped
 ports:
 - "18789:18789"
 volumes:
 - openclaw_data:/data
 env_file:
 - .env

volumes:
 openclaw_data:
Enter fullscreen mode Exit fullscreen mode

And the corresponding .env file:

ANTHROPIC_API_KEY=sk-ant-your-key-here
GATEWAY_TOKEN=your-secure-random-token
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
Enter fullscreen mode Exit fullscreen mode

This gives you a working OpenClaw instance with Claude as the AI model, Telegram as the messaging platform, persistent data storage, and the web UI accessible on port 18789.

Run it with:

docker compose up -d
Enter fullscreen mode Exit fullscreen mode

That is genuinely all you need to get started. Everything below this section covers advanced configuration and optimization.


What Environment Variables Does OpenClaw Need?

OpenClaw has dozens of environment variables, but only a few are required. Here is a categorized reference:

Required:

# At least one model provider API key
ANTHROPIC_API_KEY=sk-ant-...
# OR
OPENAI_API_KEY=sk-...
# OR
GOOGLE_AI_API_KEY=...
Enter fullscreen mode Exit fullscreen mode

Recommended:

GATEWAY_TOKEN=random-secure-string # API authentication
TELEGRAM_BOT_TOKEN=... # If using Telegram
MODEL_PRIMARY=claude-sonnet-4-20250514 # Default model
Enter fullscreen mode Exit fullscreen mode

Gateway configuration:

GATEWAY_BIND=0.0.0.0:18789 # Listen address (default)
GATEWAY_MODE=standard # standard, api_only, or reverse_proxy
Enter fullscreen mode Exit fullscreen mode

Security:

TELEGRAM_ALLOWED_USERS=123456789 # Comma-separated user IDs
AUTH_ENABLED=false # Web UI authentication
AUTH_PROVIDER=google # OAuth provider
Enter fullscreen mode Exit fullscreen mode

Sandbox:

SANDBOX_BACKEND=docker # docker, ssh, or none
SANDBOX_DOCKER_IMAGE=openclaw/sandbox:latest
Enter fullscreen mode Exit fullscreen mode

Browser:

BROWSER_ENABLED=true # Enable browser automation
BROWSER_HEADLESS=true # Run headless (default)
Enter fullscreen mode Exit fullscreen mode

Always put sensitive values in a .env file, not directly in docker-compose.yml. The .env file should be in the same directory as docker-compose.yml and should be added to .gitignore if you version control your deployment configuration.


How Do Volumes Work?

The /data volume is critical. It stores everything that needs to persist between container restarts:

  • /data/config.json — Configuration file (if not using env vars exclusively)
  • /data/sessions/ — Conversation sessions and history
  • /data/memory/ — Agent memory (vector store and file-based)
  • /data/skills/ — Installed skills (SKILL.md files)
  • /data/logs/ — Application logs (if file logging is enabled)

Without a volume, all of this data is lost every time the container restarts. This is the single most common mistake new operators make — they deploy without a volume, everything works great, the container restarts, and all conversation history and configuration is gone.

You have two options for volumes:

Named volume (recommended for most users):

volumes:
 - openclaw_data:/data
Enter fullscreen mode Exit fullscreen mode

Docker manages the storage location. Data survives container updates and recreations. Easy to back up with docker volume inspect openclaw_data to find the path.

Bind mount (for advanced users):

volumes:
 - ./openclaw-data:/data
Enter fullscreen mode Exit fullscreen mode

Maps to a specific directory on the host. Easier to access files directly, manage backups, and troubleshoot. But you are responsible for permissions and directory creation.


What Ports Does OpenClaw Use?

OpenClaw uses a single port by default: 18789. This handles all HTTP traffic — web UI, REST API, and webhook callbacks.

ports:
 - "18789:18789" # host_port:container_port
Enter fullscreen mode Exit fullscreen mode

You can change the host port without changing OpenClaw's internal configuration:

ports:
 - "8080:18789" # Access on port 8080, OpenClaw still listens on 18789 internally
Enter fullscreen mode Exit fullscreen mode

If you are running behind a reverse proxy and do not need direct external access, you can remove the ports mapping entirely and use Docker's internal networking:

# No ports exposed — only accessible via Docker network
# Other services (like Nginx) can reach openclaw:18789 via the Docker network
Enter fullscreen mode Exit fullscreen mode

If you are using the sandbox Docker backend, OpenClaw also needs access to the Docker socket:

volumes:
 - /var/run/docker.sock:/var/run/docker.sock
Enter fullscreen mode Exit fullscreen mode

This lets OpenClaw create sandbox containers. The security implications of mounting the Docker socket are significant — it gives OpenClaw the ability to create, start, stop, and delete containers. Only do this if you understand the risks.


Marketplace

Free skills and AI personas for OpenClaw — browse the marketplace.

Browse the Marketplace →

How Do You Run OpenClaw with Other Services?

A production deployment often includes companion services. Here is a complete multi-service docker-compose.yml:

version: "3.8"

services:
 openclaw:
 image: openclaw/openclaw:latest
 container_name: openclaw
 restart: unless-stopped
 volumes:
 - openclaw_data:/data
 - /var/run/docker.sock:/var/run/docker.sock
 env_file:
 - .env
 depends_on:
 - ollama
 networks:
 - openclaw_net

 caddy:
 image: caddy:2-alpine
 container_name: caddy
 restart: unless-stopped
 ports:
 - "80:80"
 - "443:443"
 volumes:
 - ./Caddyfile:/etc/caddy/Caddyfile
 - caddy_data:/data
 networks:
 - openclaw_net

 ollama:
 image: ollama/ollama:latest
 container_name: ollama
 restart: unless-stopped
 volumes:
 - ollama_data:/root/.ollama
 networks:
 - openclaw_net

volumes:
 openclaw_data:
 caddy_data:
 ollama_data:

networks:
 openclaw_net:
Enter fullscreen mode Exit fullscreen mode

This setup runs OpenClaw behind Caddy (a reverse proxy with automatic HTTPS), with Ollama available for local model inference. Caddy handles TLS certificates automatically, and all services communicate over a shared Docker network.

The corresponding Caddyfile:

your-domain.com {
 reverse_proxy openclaw:18789
}
Enter fullscreen mode Exit fullscreen mode

How Do You Update OpenClaw?

Updating OpenClaw with Docker Compose is straightforward:

# Pull the latest image
docker compose pull

# Restart with the new image
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Your data persists in the volume — only the application code changes. The container is recreated with the new image, but the /data volume remains attached.

Before updating, always check the release notes for breaking changes. Major updates (like the 3.22 release) can rename environment variables, change config formats, or remove deprecated features.

To pin a specific version instead of using latest:

image: openclaw/openclaw:3.23.1
Enter fullscreen mode Exit fullscreen mode

This prevents unexpected updates and gives you control over when you upgrade. Many operators pin to a specific version in production and test new versions in a staging environment first.


What Are the Most Common Docker Issues?

"Port 18789 is already in use" — Another process is using the port. Change the host port in docker-compose.yml (e.g., "8080:18789") or stop the conflicting process.

"Permission denied" on volume mount — The host directory has wrong ownership. Run sudo chown -R 1000:1000 ./openclaw-data (1000 is the default UID inside the container).

Container restarts in a loop — Check logs with docker compose logs openclaw. Common causes: invalid config, expired API key, or missing required environment variables.

"No space left on device" — Docker images, containers, and volumes consume disk space. Run docker system prune to clean up unused resources. Also check if conversation logs are filling the data volume.

Environment variables not updating — Docker Compose can cache the old environment. Run docker compose up -d --force-recreate instead of just docker compose restart to ensure the new .env values are loaded.

"Cannot connect to Docker daemon" — The Docker daemon is not running, or your user does not have permission. Run sudo systemctl start docker and add your user to the docker group with sudo usermod -aG docker $USER.

Top comments (0)