Skip to main content
better-openclaw generates production-ready Docker Compose stacks with automatic port conflict detection, health checks, and resource limits. This is the default and recommended deployment method.

Prerequisites

  • Docker Engine 20.10+
  • Docker Compose v2.0+
  • 2GB+ available RAM (varies by preset)
  • Linux (amd64 or arm64) or macOS

Quick start

1

Generate a stack

Run the CLI to generate your stack configuration:
npx create-better-openclaw@latest --preset researcher
This creates:
  • docker-compose.yml — Service definitions with health checks and dependencies
  • .env — Environment variables with auto-generated secrets
  • Caddyfile or traefik.yml — Reverse proxy configuration (if selected)
  • README.md — Stack-specific documentation
2

Review the configuration

Inspect the generated docker-compose.yml to verify services, ports, and volumes:
cat docker-compose.yml
Check for port conflicts with running services:
docker compose config
3

Start the stack

Launch all services in detached mode:
docker compose up -d
Monitor startup logs:
docker compose logs -f
4

Verify health

Check that all services are healthy:
docker compose ps
All services should show healthy status. If any service fails, check logs:
docker compose logs <service-name>

Stack management

Stop services

Stop all containers without removing them:
docker compose stop
Stop a specific service:
docker compose stop redis

Restart services

Restart all services:
docker compose restart
Restart a specific service:
docker compose restart postgresql

Remove stack

Stop and remove all containers, networks, and anonymous volumes:
docker compose down
Remove everything including named volumes (⚠️ deletes all data):
docker compose down -v

Development workflow

Adding services

Add a service to an existing stack:
npx create-better-openclaw add grafana
This updates docker-compose.yml and .env with the new service and its dependencies.

Removing services

Remove a service from the stack:
npx create-better-openclaw remove grafana

Updating services

Pull the latest images:
docker compose pull
Recreate containers with new images:
docker compose up -d --force-recreate

Production deployment

Resource limits

better-openclaw sets memory limits for all services. For production workloads, review and adjust limits in docker-compose.yml:
services:
  redis:
    mem_limit: 1g
    mem_reservation: 512m

Persistent volumes

All data-bearing services use named volumes for persistence. Back up volumes regularly:
# List volumes
docker volume ls

# Backup a volume
docker run --rm -v <volume-name>:/data -v $(pwd):/backup \
  alpine tar czf /backup/volume-backup.tar.gz -C /data .

Health checks

Every service includes health checks. Configure dependency ordering with depends_on.condition:
services:
  n8n:
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy

Environment variables

Never commit .env files to version control. Use .env.example as a template:
cp .env.example .env
# Edit .env with production secrets

Multi-host deployment

For multi-server deployments, use Docker Swarm or migrate to Dokploy or Coolify.

Docker Swarm example

Initialize swarm:
docker swarm init
Deploy stack:
docker stack deploy -c docker-compose.yml openclaw

Monitoring

If you selected the DevOps preset or added Grafana and Prometheus, access monitoring at:
  • Grafana: http://localhost:3000 (default credentials in .env)
  • Prometheus: http://localhost:9090
All services expose metrics via /metrics endpoints when available.

Troubleshooting

Port conflicts

The CLI auto-detects port conflicts during generation. If you encounter conflicts after deployment:
# Check what's using a port
lsof -i :5432

# Regenerate with custom ports
npx create-better-openclaw --proxy-http-port 8080 --proxy-https-port 8443

Container startup failures

Check logs for the failing service:
docker compose logs <service-name>
Inspect the container:
docker inspect <container-name>

Disk space issues

Clean up unused Docker resources:
# Remove unused containers, networks, and images
docker system prune -a

# Remove unused volumes (⚠️ deletes data)
docker volume prune

Reference docker-compose.yml

Here’s the structure of a generated docker-compose.yml:
services:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    mem_limit: 512m
    healthcheck:
      test: redis-cli ping
      interval: 5s
      timeout: 3s
      retries: 5
    restart: unless-stopped
    networks:
      - openclaw-network

  postgresql:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    mem_limit: 1g
    healthcheck:
      test: pg_isready -U ${POSTGRES_USER}
      interval: 5s
      timeout: 3s
      retries: 5
    restart: unless-stopped
    networks:
      - openclaw-network

volumes:
  redis-data:
  postgres-data:

networks:
  openclaw-network:
    driver: bridge

Next steps

Build docs developers (and LLMs) love