Docker Deployment
Docker is the fastest way to get OpenClaw running in a reproducible, isolated environment. This guide walks you through a production-ready Docker setup — from a simple single-container run to a full docker-compose stack with Redis, PostgreSQL, and health checks.
Prerequisites
- Docker Engine 24+ installed (
docker --version) - docker-compose v2+ (
docker compose version) - At least one LLM provider API key (OpenAI, Anthropic, or Ollama locally)
- 2GB free RAM minimum (4GB recommended for production)
Quick Start — Single Container
Run OpenClaw with a single docker run command for testing or lightweight use:
docker run -d --name openclaw -e OPENAI_API_KEY=sk-your-key -p 8080:8080 -v openclaw-data:/app/data ghcr.io/openclaw-ai/openclaw:latest# Test it works
curl http://localhost:8080/health
# {"status": "ok", "version": "1.5.2"}
# Run a task via API
curl -X POST http://localhost:8080/tasks -H "Content-Type: application/json" -d '{"prompt": "List 3 benefits of containerization"}'Custom Dockerfile
For production, build your own image that includes your custom agents and plugins:
FROM python:3.12-slim
# Security: run as non-root user
RUN addgroup --system openclaw && adduser --system --ingroup openclaw openclaw
WORKDIR /app
# Install dependencies first (better layer caching)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application
COPY --chown=openclaw:openclaw . .
USER openclaw
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 CMD curl -f http://localhost:8080/health || exit 1
EXPOSE 8080
CMD ["openclaw", "serve", "--host", "0.0.0.0", "--port", "8080"]requirements.txt:
openclaw==1.5.2
openclaw[redis]==1.5.2 # Include Redis backend
gunicorn==21.2.0 # Production WSGI serverProduction docker-compose.yml
For a complete stack with Redis caching and PostgreSQL persistence:
version: "3.9"
services:
openclaw:
image: ghcr.io/openclaw-ai/openclaw:1.5.2
restart: unless-stopped
ports:
- "8080:8080"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- OPENCLAW_ENV=production
- REDIS_URL=redis://redis:6379/0
- DATABASE_URL=postgresql://openclaw:${DB_PASS}@db:5432/openclaw
depends_on:
redis:
condition: service_healthy
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
cpus: "2"
memory: 1G
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: openclaw
POSTGRES_USER: openclaw
POSTGRES_PASSWORD: ${DB_PASS}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U openclaw"]
interval: 10s
timeout: 5s
retries: 5
volumes:
redis-data:
db-data:# Create .env file (never commit this!)
echo "OPENAI_API_KEY=sk-your-key" > .env
echo "DB_PASS=$(openssl rand -base64 32)" >> .env
# Start the stack
docker compose up -d
# Check all services are healthy
docker compose psSecurity Hardening
Docker containers provide some isolation by default, but production deployments should apply additional hardening:
- Non-root user — already in the Dockerfile above; never run as root
- Read-only filesystem — add
read_only: trueto the service and mount specific writable paths as volumes - No new privileges — add
security_opt: ["no-new-privileges:true"] - Drop Linux capabilities — add
cap_drop: [ALL]and only add back what's needed - Secrets via Docker secrets — don't put API keys in environment variables in
.envfiles in production; use Docker secrets or a vault
# Hardened service configuration
services:
openclaw:
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
tmpfs:
- /tmp
volumes:
- openclaw-data:/app/data # Writable volume for dataLogs and Monitoring
# Stream logs from all services
docker compose logs -f
# Only OpenClaw logs
docker compose logs -f openclaw
# Filter for errors only
docker compose logs openclaw | grep '"level":"error"'Configure log rotation to prevent disk exhaustion:
services:
openclaw:
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"For structured log shipping to Datadog, Loki, or Elasticsearch, see Structured Logging.
Production Docker Configuration
A production-ready Docker configuration for OpenClaw addresses security, resource limits, logging, and health checking. The minimal production docker-compose.yml includes: a resource limits block to prevent the container from consuming unbounded memory (mem_limit: 512m for most agents), a health check that verifies the agent process is responsive, a restart policy of unless-stopped for automatic recovery from crashes, and read-only filesystem with a specific writeable volume for logs and agent memory. These four elements together make the container self-healing and resource-bounded.
Multi-stage Docker builds keep production images small and secure. Use a build stage to assemble the application with all build tools installed, then copy only the necessary artifacts to a minimal runtime image. A Python OpenClaw deployment might use a python:3.11-slim build stage and a python:3.11-alpine runtime stage, reducing the final image size by 60-70% and eliminating build tools (pip, gcc, make) from the production image. Smaller images have a smaller attack surface and deploy faster due to reduced pull time.
Secrets Handling in Docker
Never bake secrets into Docker images — once a secret is in an image layer, it's accessible to anyone who can pull the image, even if you add a later layer that removes the file. Pass secrets at runtime using Docker secrets (in Swarm mode) or environment variables injected by your deployment system. For Docker Compose on a single host, use a .env file that is excluded from version control via .gitignore. Verify your .gitignore contains .env before committing — accidentally committing credentials is one of the most common security incidents in containerized deployments.
Container Registry and Image Scanning
Maintain your OpenClaw images in a private container registry (Docker Hub private, ECR, GCR, or Azure Container Registry). Enable vulnerability scanning on your registry — most cloud registries offer this built-in. Configure your CI pipeline to fail the build if the image scan finds high-severity CVEs in base OS packages or Python dependencies. Regularly update your base image to pick up security patches, and track the OpenClaw release notes for dependency updates. A well-maintained image as of deployment date that is never updated will accumulate vulnerabilities — treat image updates as ongoing operational work, not a one-time task.