Guía9 min

Compose profiles para un agente IA: migrate no es el webhook

Resumen

Cómo no dejar Adminer y el job migrate 24/7 en prod: profiles de Compose, COMPOSE_PROFILES y el webhook sin profile. Distinto de depends_on healthy. Regex de nombres, --profile '*' y compose run que auto-activa. Techos oficiales Docker Compose, curl 3 de septiembre de 2026.

Docker
Servicios Compose con profiles tools apagados junto al webhook en prod

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

Adminer, migrate y un worker de debug en el mismo yaml sin profile salen con up -d en prod. Profiles: opt-in. El webhook no lleva profiles (siempre on). Fuentes oficiales consultadas el 3 de septiembre de 2026.

depends_on healthy ordena Postgres. Esta guía es qué ni siquiera se crea.

La regla

services:
  agent:
    image: agent:pinned
  postgres:
    image: postgres:18
  migrate:
    image: agent:pinned
    command: ["node", "migrate.mjs"]
    profiles: ["tools"]
    depends_on:
      postgres:
        condition: service_healthy
  adminer:
    image: adminer
    profiles: ["tools"]

Prod: docker compose up -d sin COMPOSE_PROFILES. Tools: COMPOSE_PROFILES=tools docker compose up o docker compose --profile tools up.

El spec (curl 2026-09-03): sin profiles, el servicio siempre está habilitado. Con lista, Compose lo ignora si ningún nombre coincide con los perfiles activos.

Nombres válidos: regex [a-zA-Z0-9][a-zA-Z0-9_.-]+. tools, debug, migrate sí. Empieza con letra o dígito.

La guía oficial dice que los servicios core no lleven profile. El agente, Postgres y Caddy son core. Adminer no.

Cómo se encienden

CLI (docs docker compose, curl 2026-09-03): --profile “Specify a profile to enable”. Varios: --profile frontend --profile debug. Equivale a COMPOSE_PROFILES=frontend,debug (coma, sin espacio en el ejemplo oficial).

COMPOSE_PROFILES (envvars oficiales): al correr docker compose up, arranca los que coinciden más los que no tienen profile. COMPOSE_PROFILES=frontend no apaga Postgres.

Todos a la vez: docker compose --profile "*". No lo dejes en el unit de systemd del VPS.

.env del directorio del compose puede setear COMPOSE_PROFILES. Si copias el .env del laptop al VPS “porque así arranca todo”, Adminer vive 24/7. dockerignore no cubre el env del host.

Target explícito (migrate one-shot)

Si apuntas el servicio en la línea de comando, Compose añade su profile al set activo. No hace falta --profile tools para un one-shot:

docker compose up -d
docker compose run --rm migrate

--rm (docs compose run): borra el contenedor al terminar aunque el servicio tenga restart policy. Eso es el job de migrate, no un daemon.

Ojo: al targetear migrate, arranca él y sus depends_on (Postgres). No arranca el resto del profile tools. Adminer sigue off hasta --profile tools o COMPOSE_PROFILES=tools.

Si el target tiene depends_on a otro servicio también con profile, ese dependency tiene que: compartir profile, arrancar aparte, o no tener profile. Si no, el modelo es inválido.

depends_on vs profiles

No pongas depends_on: migrate en el webhook. En prod migrate no existe. required default true (Compose 2.20.0+): Compose se queja. El webhook no espera un one-shot.

Migraciones: compose run --rm migrate en el deploy, o condition: service_completed_successfully en un up de CI, no en el daemon 24/7.

Postgres es service_healthy y sin profile.

links, extends y service:xxx no encienden un profile ignorado: Compose error. No uses un alias para “traer” Adminer.

Qué no cubre el profile

El spec: solo el top-level services filtra. Networks, volumes, secrets, configs siguen activos aunque Adminer esté off. Una network tools declarada no desaparece. Networks sigue haciendo falta: no publiques 8080.

Profile no es firewall. Quien tenga SSH hace --profile tools up. Cierra ports igual.

Tabla

Webhook siempre on versus tools opt-in

ServicioProfileup -d prodCómo encenderlo
agente(ninguno)siempre
postgres(ninguno)siempre
caddy(ninguno)siempre
migratetoolsnocompose run --rm migrate
adminertoolsno--profile tools

Ensayo: docker compose config --services (flag oficial: un nombre por línea) sin env no lista adminer. Con COMPOSE_PROFILES=tools, sí. docker compose config --profiles lista los nombres de profile.

docker compose down sin profile solo baja los unassigned (agente/postgres/caddy). COMPOSE_PROFILES=tools docker compose down baja tools y unassigned. Para bajar solo Adminer: docker compose down adminer / stop adminer.

Varios profiles

Un servicio en ["tools", "debug"] se enciende si cualquiera está activo (unión). COMPOSE_PROFILES=tools no enciende un servicio que solo tiene debug.

No pongas prod como profile del webhook. El core va sin atributo.

Preview vs prod

Preview del VPS puede COMPOSE_PROFILES=tools. Prod: vacío. Preview vs production es el criterio; aquí el knob es el env.

CI (Actions): job de migrate con compose run --rm, no up --profile tools -d que deja Adminer.

Fly / Railway / Workers

No hay profiles: de Compose. Fly: [processes] / process groups en fly.toml (docs de configuration, curl 2026-09-03): HTTP processes limita qué grupo recibe requests. Un migrate es otro process group o una Machine one-shot, no un profile. Railway: otro servicio. Workers no es Compose.

Errores comunes

Adminer escuchando en prod

SíntomaCausaFix
Adminer en :8080 prodsin profilesprofiles: ["tools"]
webhook no arrancaprofile en el agentequítalo
up falla por migratedepends_on + required truejob run --rm
.env con COMPOSE_PROFILES=toolscopy del laptopvacío en prod
down deja Adminerdown sin profiledown adminer o profile en down
run migrate levanta Adminerno: solo target + depends_onno uses --profile tools para un job
Fly profiles:no existeprocess groups
scale: 0 “como profile”el servicio sigue existiendoprofile ni se crea

Relación con el resto

Checklist

  • Agente / postgres / caddy sin profiles
  • adminer / migrate con tools (regex válida)
  • Prod sin COMPOSE_PROFILES en systemd ni .env del host
  • Ensayo: compose config --services en prod no lista adminer
  • Migraciones: compose run --rm migrate, no daemon
  • Documenta up --profile tools para debug
  • Sin ports de tools 24/7
  • depends_on del webhook no apunta a migrate

FAQ

¿scale: 0 en vez de profiles? Peor: el servicio existe en el modelo. Profile ni se crea.

¿Un compose.prod.yml? Válido. Profiles evitan dos archivos si el yaml es uno.

¿K8s? Jobs vs Deployments. Mismo criterio: migrate no es ReplicaSet del webhook.

¿Un worker de cola? Si es 24/7, sin profile. Si es batch semanal, profile batch y un cron compose --profile batch run --rm.

¿enabled: false de un plugin? No. El knob oficial es profiles.

¿Profile en Postgres “para ahorrar”? El agente sin DB es crash loop. Core siempre on.

El ensayo extra: clone del yaml de prod; up -d; ps sin adminer. up --profile tools; aparece. COMPOSE_PROFILES=tools compose config --services incluye adminer; sin env, no.

Siguiente paso: si tools ya están off y 8080 igual abre, networks y ports. Sin runtime: curso.