-
-
Notifications
You must be signed in to change notification settings - Fork 0
Profile Implementation Guide
This document explains how service profiles are implemented in DevStack Core using Docker Compose native profile support.
Each service in docker-compose.yml has a profiles: key that determines which profiles will start that service.
| Service | Profiles | Rationale |
|---|---|---|
| vault | (none) | Always starts - required for credential management |
| postgres | minimal, standard, full | Core database for all profiles |
| pgbouncer | minimal, standard, full | Connection pooling for PostgreSQL |
| forgejo | minimal, standard, full | Git server available in all profiles |
| redis-1 | minimal, standard, full | Single Redis in minimal, cluster node 1 in standard/full |
| redis-2 | standard, full | Cluster node 2 (only in standard+) |
| redis-3 | standard, full | Cluster node 3 (only in standard+) |
| mysql | standard, full | Additional database (standard+) |
| mongodb | standard, full | NoSQL database (standard+) |
| rabbitmq | standard, full | Message queue (standard+) |
| prometheus | full | Metrics collection (full only) |
| grafana | full | Visualization (full only) |
| loki | full | Log aggregation (full only) |
| vector | full | Observability pipeline (full only) |
| cadvisor | full | Container monitoring (full only) |
| redis-exporter-1 | full | Redis metrics for node 1 (full only) |
| redis-exporter-2 | full | Redis metrics for node 2 (full only) |
| redis-exporter-3 | full | Redis metrics for node 3 (full only) |
| reference-api | reference | Python FastAPI code-first |
| api-first | reference | Python FastAPI API-first |
| golang-api | reference | Go with Gin |
| nodejs-api | reference | Node.js with Express |
| rust-api | reference | Rust with Actix-web |
- vault - No profile assignment means it starts with ANY profile or when no profile is specified
┌─────────────────────────────────────────────────────┐
│ MINIMAL (5 services, 2GB RAM) │
│ • vault, postgres, pgbouncer, forgejo, redis-1 │
└─────────────────────────────────────────────────────┘
│
│ adds: mysql, mongodb, redis-2,
│ redis-3, rabbitmq
▼
┌─────────────────────────────────────────────────────┐
│ STANDARD (12 services, 4GB RAM) │
│ • All minimal services │
│ • + mysql, mongodb, redis-2/3, rabbitmq │
└─────────────────────────────────────────────────────┘
│
│ adds: prometheus, grafana, loki,
│ vector, cadvisor, exporters
▼
┌─────────────────────────────────────────────────────┐
│ FULL (18 services, 6GB RAM) │
│ • All standard services │
│ • + prometheus, grafana, loki, vector, cadvisor │
│ • + redis-exporter-1/2/3 │
└─────────────────────────────────────────────────────┘
┌───────────────┐
│ REFERENCE │
│ (5 services) │
│ +1GB RAM │
└───────────────┘
│
│ Can combine with any profile
▼
┌──────────────┬──────────────┬──────────────┐
│ minimal │ standard │ full │
│ +reference │ +reference │ +reference │
└──────────────┴──────────────┴──────────────┘
services:
postgres:
profiles: ["minimal", "standard", "full"]
image: postgres:18
# ... rest of configurationservices:
vault:
# No profiles key = starts with any profile
image: vault:latest
# ... rest of configuration# Start with specific profile
docker compose --profile minimal up -d
# Combine multiple profiles
docker compose --profile standard --profile reference up -d
# Start without any profile (only services without profiles key)
docker compose up -d # Only starts vaultWhen running minimal profile:
- Only
redis-1starts - Redis runs in standalone mode (not cluster)
- No cluster initialization needed
- Direct connection:
redis-cli -h localhost -p 6379
When running standard or full profiles:
- All three Redis nodes start (
redis-1,redis-2,redis-3) - Cluster mode enabled in redis.conf
- Cluster initialization required after first start
- Cluster connection:
redis-cli -c -h localhost -p 6379
All services depend on Vault:
services:
postgres:
depends_on:
vault:
condition: service_healthyThis ensures:
- Vault starts first
- Vault becomes healthy (unsealed + initialized)
- Only then do other services start
- Services can fetch credentials from Vault
Services only depend on services in the same or broader profile:
services:
redis-exporter-1:
profiles: ["full"]
depends_on:
vault:
condition: service_healthy
redis-1:
condition: service_startedSince redis-exporter-1 is only in full profile, and redis-1 is in minimal, standard, and full, the dependency is always satisfied.
All services maintain their health checks regardless of profile:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 60s
timeout: 5s
retries: 5
start_period: 30sThe management script can check health with:
./devstack.py healthEach profile has optional environment override files:
configs/profiles/
├── minimal.env # Overrides for minimal profile
├── standard.env # Overrides for standard profile
├── full.env # Overrides for full profile
└── reference.env # Overrides for reference profile
Example configs/profiles/minimal.env:
# Redis configuration for minimal profile
REDIS_CLUSTER_ENABLED=false
REDIS_CLUSTER_INIT_REQUIRED=false
# Reduced connection limits for lighter workload
POSTGRES_MAX_CONNECTIONS=50
MYSQL_MAX_CONNECTIONS=50
# Faster health checks (smaller stack)
POSTGRES_HEALTH_INTERVAL=30s
VAULT_HEALTH_INTERVAL=30sExample configs/profiles/standard.env:
# Redis cluster configuration
REDIS_CLUSTER_ENABLED=true
REDIS_CLUSTER_INIT_REQUIRED=true
# Standard connection limits
POSTGRES_MAX_CONNECTIONS=100
MYSQL_MAX_CONNECTIONS=100
MONGODB_MAX_CONNECTIONS=100
# Standard health check intervals
POSTGRES_HEALTH_INTERVAL=60s
VAULT_HEALTH_INTERVAL=60s-
Minimal Profile
docker compose --profile minimal config --services # Should output: vault, postgres, pgbouncer, forgejo, redis-1 docker compose --profile minimal up -d docker ps --format "table {{.Names}}\t{{.Status}}" # Verify only 5 containers running
-
Standard Profile
docker compose --profile standard config --services # Should output: vault, postgres, pgbouncer, forgejo, redis-1/2/3, mysql, mongodb, rabbitmq docker compose --profile standard up -d docker ps --format "table {{.Names}}\t{{.Status}}" # Verify 12 containers running
-
Full Profile
docker compose --profile full config --services # Should output: all standard services + prometheus, grafana, loki, vector, cadvisor, exporters docker compose --profile full up -d docker ps --format "table {{.Names}}\t{{.Status}}" # Verify 18 containers running
-
Combined Profiles
docker compose --profile standard --profile reference config --services # Should output: all standard services + all reference apps docker compose --profile standard --profile reference up -d docker ps --format "table {{.Names}}\t{{.Status}}" # Verify 17 containers running (12 standard + 5 reference)
Measure actual resource usage:
# Total RAM usage by profile
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}" | \
awk '{sum+=$2} END {print "Total RAM:", sum/1024/1024/1024, "GB"}'
# Per-service RAM
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}"Expected results:
- Minimal: ~2GB RAM
- Standard: ~4GB RAM
- Full: ~6GB RAM
# Currently running standard profile
docker compose --profile standard ps
# Stop standard profile services
docker compose --profile standard down
# Start minimal profile
docker compose --profile minimal up -d# Add standard profile services to running minimal
docker compose --profile standard up -d
# This will:
# 1. Keep running minimal services (vault, postgres, etc.)
# 2. Start additional standard services (mysql, mongodb, redis-2/3, rabbitmq)# Stop all services
docker compose --profile standard down
# Start only minimal
docker compose --profile minimal up -d
# Or remove specific services:
docker compose rm -sf mysql mongodb redis-2 redis-3 rabbitmqMorning Routine (Standard Profile):
./devstack.py start --profile standard
./devstack.py health
./devstack.py redis-cluster-init # First time onlyEnd of Day:
./devstack.py stopWeekend (Keep Minimal Running):
# Stop standard, keep minimal (Git server stays up)
docker compose --profile standard down
docker compose --profile minimal up -dGitHub Actions (Minimal for Tests):
- name: Start DevStack Core
run: |
docker compose --profile minimal up -d
docker compose --profile minimal psLoad Testing (Full Profile):
- name: Start DevStack Core with Observability
run: |
docker compose --profile full up -d
./wait-for-health.shCheck if service is in the profile:
docker compose --profile minimal config --services | grep mysql
# Empty output = mysql not in minimal profileCheck running containers:
docker ps --format "{{.Names}}" | grep dev-Compare with expected services:
docker compose --profile minimal config --servicesIf services from multiple profiles are running:
# Nuclear option: stop everything
docker compose down --remove-orphans
# Start clean with desired profile
docker compose --profile standard up -d- Always specify profile - Don't rely on defaults
- Use minimal for CI/CD - Faster, lighter
- Use standard for development - Full feature set
- Use full for performance testing - Observability included
- Combine reference with others - Learn patterns alongside dev
- Document custom profiles - Add to profiles.yaml custom_profiles section
- Test profile switches - Ensure services stop/start correctly
- Monitor resources - Validate RAM estimates match reality
- Create profiles.yaml with profile definitions
- Document profile implementation strategy
- Add
profiles:keys to docker-compose.yml - Create profile-specific environment files
- Test minimal profile (5 services)
- Test standard profile (12 services)
- Test full profile (18 services)
- Test reference profile (5 services)
- Test combined profiles (standard + reference)
- Validate resource usage matches estimates
- Update documentation (README, INSTALLATION, USAGE)
- Create Python management script with profile support
- Add profile validation to CI/CD pipeline