Footgun Dokploy: env vars en UI que no llegan al container
El problema
Dokploy no hace merge de variables de entorno entre su panel UI y el compose.yml/compose.prod.yml. Si una variable está configurada en el panel de Dokploy pero no aparece listada en el bloque environment: del servicio en el compose, la variable nunca llega al container en tiempo de ejecución.
Esto es contrario a la intuición de quien viene de otros PaaS (Railway, Render, Fly.io) donde las env vars del panel se inyectan independientemente del compose.
Síntoma clásico
El container arranca sin error. Los logs no muestran nada sospechoso. El código Python lee la variable con os.environ.get("MI_VAR", "default") y silenciosamente usa el default — aunque en el panel de Dokploy la variable esté correctamente seteada con otro valor.
El bug es especialmente traicionero porque:
- No hay warning ni error en los logs de Dokploy.
- El panel muestra la variable como “configurada”.
- El comportamiento es funcional (usa el default), solo incorrecto.
Incidente real: s48 OpenRouter provider order
Detectado el 2026-05-03 durante la primera prueba PROD del switch de Auto-Plan a OpenRouter:
- Variable
OPENROUTER_PROVIDER_ORDER=DekaLLM,Novita,Ionstream✅ configurada en panel Dokploy. - Variable no listada en
compose.yml/compose.prod.yml❌. - Resultado: el driver leyó siempre el default hardcoded y OpenRouter ruteó por disponibilidad → sirvió Ionstream (calidad ~20%) en vez de DekaLLM (calidad 100%).
- Fix:
34895cd— añadidaOPENROUTER_PROVIDER_ORDER=${OPENROUTER_PROVIDER_ORDER:-}a los 3 servicios afectados (web dev, web prod, worker prod).
La regla
Toda variable de entorno que deba llegar a un container en Dokploy DEBE aparecer explícitamente en el bloque
environment:del servicio correspondiente encompose.ymlocompose.prod.yml.
Patrón recomendado
services:
web:
environment:
# Variables con valor literal (siempre presentes)
- DJANGO_SETTINGS_MODULE=core.settings.production
# Variables desde el host/Dokploy (con fallback vacío)
- MI_VARIABLE=${MI_VARIABLE:-}
# Variables con fallback no vacío (default explícito)
- OTRA_VARIABLE=${OTRA_VARIABLE:-valor_default}
El patrón ${VAR:-} expone la variable con string vacío como fallback cuando no está seteada en el host. Esto es diferente a omitirla: al estar listada, Dokploy/Docker la incluye en el entorno del proceso.
Servicios afectados en CreaRack Pro
Los servicios que requieren variables de entorno controlables desde Dokploy son:
| Servicio | Compose | Variables críticas |
|---|---|---|
web (dev) | compose.yml | OPENROUTER_API_KEY, OPENROUTER_PROVIDER_ORDER, GEMINI_API_KEY, AUTOPLAN_PROVIDER |
web (prod) | compose.prod.yml | Ídem + VICTORIAMETRICS_URL, MIB_CACHE_DIR |
worker (prod) | compose.prod.yml | OPENROUTER_API_KEY, OPENROUTER_PROVIDER_ORDER, GEMINI_API_KEY, AUTOPLAN_PROVIDER, EDGE_AI_PROVIDER |
Checklist al añadir una nueva env var
- ¿Está en
compose.yml→ bloqueenvironment:del servicio que la usa? - ¿Está en
compose.prod.yml→ bloqueenvironment:de todos los servicios que la usan (web + worker si aplica)? - ¿Se ha documentado en
CLAUDE.md(sección de env vars) si es una variable de configuración de comportamiento? - ¿Tiene un fallback razonable (
${VAR:-default}) para entornos locales sin.env?
Por qué pasa esto en Dokploy
Dokploy gestiona env vars en su BD interna y las pasa al docker-compose up como variables del entorno del proceso que ejecuta Docker. Docker Compose solo propaga al container las variables que menciona explícitamente en el bloque environment: (interpolación ${VAR}). Las variables del entorno del proceso anfitrión que no están referenciadas en el compose nunca se inyectan — es comportamiento estándar de Docker Compose, no un bug de Dokploy.
Véase también
- [[entity—blueprints—service—openrouter-driver]]
- [[feature—blueprints—autoplan]]
- [[runbook—infra—rotate-mcp-token]]