Docker Compose Best Practices for Multi-Service Stacks
Essential best practices for managing Docker Compose files with 10+ services — networking, health checks, resource limits, dependency ordering, and more.
Running 10, 20, or even 50 services in a single Docker Compose stack is common in modern AI and DevOps setups. But without proper configuration, you'll hit port conflicts, memory exhaustion, race conditions, and silent failures. Here are the practices we've baked into every better-openclaw-generated stack.
Pin Your Image Tags
Never use :latest in production. Pin to specific versions (e.g., postgres:16.2-alpine) to ensure reproducible deployments. better-openclaw pins every image tag in its service registry and updates them with each release. This prevents surprise breaking changes when containers restart.
Health Checks Are Non-Negotiable
Every service should have a health check. Without one, Docker reports a container as "running" even if the application inside has crashed. Use HTTP health endpoints for web services, pg_isready for PostgreSQL, redis-cli ping for Redis, and similar native checks. better-openclaw generates appropriate health checks for all 94 supported services.
Set Resource Limits
Without memory limits, a single runaway service can OOM-kill your entire stack. Set mem_limit and cpus for every service. A reasonable default is 512 MB for lightweight services, 1–2 GB for databases, and 4–8 GB for LLM runners. better-openclaw calculates and sets these based on each service's known requirements.
Dependency Ordering
Use depends_on with condition: service_healthy to ensure services start in the right order. Databases should be healthy before application services start. Without health-check-based ordering, your app might try to connect to a database that's still initializing, causing cryptic startup failures.