Este modelo es el que se ejecuta bajo
make up en desarrollo local y bajo el chart de Helm en Kubernetes. Si usas make up, no necesitas ningún paso manual. El stack de Compose bloquea la aplicación hasta que se complete el runner de migración.Por qué un runner dedicado
El antiguo migrador en proceso se ejecutaba en cada arranque de la aplicación desde el directorio de trabajo. Bajo un contexto de seguridad de pod reforzado (
distroless:nonroot, runAsUser: 1000, readOnlyRootFilesystem: true, capabilities: drop [ALL]), esa ruta fallaba con permission denied y el pod entraba en un ciclo de fallos.
El runner dedicado evita eso:
- Las migraciones se ejecutan una vez, como un paso separado, antes de que la aplicación arranque.
- La imagen de la aplicación ya no incluye el SQL de migración y nunca escribe en el esquema.
- La propia imagen del runner funciona sin problemas bajo el mismo contexto de seguridad reforzado (consulta Postura de seguridad).
Imágenes del runner
Cada versión incluye dos imágenes:
Ambas imágenes comparten la misma forma:
- Base:
migrate/migratev4.19.1(fijada). - Se ejecuta como
USER 65532:65532(sin root, agnóstico al UID). - Punto de entrada en shell POSIX que arma un DSN a partir de variables de entorno, ejecuta
migrate ... upy termina. - No escribe nada en disco. Postgres registra el progreso de la migración en la tabla
schema_migrations, por lo quereadOnlyRootFilesystem: truees seguro.
Contrato de entorno
Cada punto de entrada acepta una anulación de URL ya construida o las variables individuales
DB_*. La anulación de URL tiene prioridad cuando está definida.
Runner del Ledger
Runner de Tracer
Forma del DSN
Cuando el punto de entrada arma el DSN a partir de las variablesDB_*, produce:
% @ : / ? # & + space [ ]) no rompan el DSN. El % se codifica primero para que los escapes ya insertados no se codifiquen dos veces.
El punto de entrada solo registra marcadores de fase (applying onboarding migrations, applying transaction migrations, applying tracer migrations, migrations complete). Nunca imprime credenciales ni el DSN ensamblado.
Desarrollo local
make up
Desde la raíz del repositorio, make up:
- Inicia la infraestructura y espera hasta que Postgres esté disponible.
- Inicia los servicios de Compose de ejecución única
ledger-migrateytracer-migrate. - Inicia cada servicio de la aplicación, que depende (
depends_on) de su servicio de migración concondition: service_completed_successfully.
Objetivos de make en el host
Cada componente expone objetivos de Make en el host que ejecutan migraciones directamente contra una base de datos local, por ejemplo cuando desarrollas una migración nueva. Los objetivos usan la CLI fijada de golang-migrate y leen la configuración de conexión desde .env.
Ledger (components/ledger):
Tracer (
components/tracer):
Ejemplo: ejecutar el runner del Ledger manualmente
Rara vez necesitas invocar la imagen del runner manualmente, porque la puerta de Compose lo hace por ti. Cuando lo necesites, apunta el runner a tus bases de datos medianteDB_* (o *_DATABASE_URL) y ejecútalo una vez:
0 en caso de éxito (incluido el caso idempotente sin efecto) y con un valor distinto de cero en caso de error.
Despliegue en Kubernetes
En producción, ejecuta cada runner de migración como un Job de Kubernetes (normalmente un Job PreSync de Argo CD o un hook de Helm) que se completa antes del rollout de la aplicación. El chart de Helm configura esto por ti. Las secciones siguientes cubren las propiedades que importan si escribes tus propios manifiestos.
En despliegues multi-tenant, el runner es intencionalmente agnóstico al tenant: migra las bases de datos indicadas por su entorno, una vez. El fan-out por tenant es un asunto del despliegue. Ejecuta el Job una vez por cada base de datos de tenant con los valores
DB_* (o la anulación de URL) de ese tenant.Postura de seguridad
El runner funciona bajo un contexto de seguridad de pod reforzado:- Sin root: la imagen establece
USER 65532:65532. - Agnóstico al UID: los archivos de migración pertenecen a root y son legibles por cualquier usuario, de modo que cualquier UID puede leerlos.
- Seguro para
readOnlyRootFilesystem:migrateno escribe ningún estado en el sistema de archivos.
runAsNonRoot: true, readOnlyRootFilesystem: true y capabilities: drop [ALL].
TLS
Los puntos de entrada respetansslmode desde el entorno (DB_ONBOARDING_SSLMODE, DB_TRANSACTION_SSLMODE o DB_SSL_MODE), con disable como valor predeterminado. En producción se recomienda establecer require (o algo más estricto). El runner en shell no reproduce la aplicación de TLS en código, la clasificación de errores ni la telemetría que las aplicaciones usan para sus propias conexiones. Controlas el TLS de las migraciones únicamente a través de sslmode, a cambio de un runner mínimo y sin dependencias.
Convenciones e idempotencia
- Up/down emparejados: cada migración tiene un archivo
.up.sqly un archivo.down.sql. - Idempotente: ejecutar
migrate upcuando el esquema ya está en la última versión no tiene efecto. Volver a ejecutar el runner después de una aplicación parcial o completa es seguro. - CLI fijada: las imágenes del runner y los objetivos de
makeen el host fijan todosgolang-migrateenv4.19.1.
Actualización desde versiones anteriores
No necesitas ninguna migración manual de datos si actualizas desde una versión de Midaz en la que la aplicación migraba al iniciar. El esquema en disco es el mismo. Para adoptar el nuevo modelo:
- Descarga la versión que incluye las imágenes del runner.
- En Kubernetes, agrega los Jobs
midaz-ledger-migrationsymidaz-tracer-migrationsa tu pipeline de despliegue para que se ejecuten antes del rollout de la aplicación. Si usas el chart de Helm oficial, esto ya está hecho por ti. - En desarrollo local,
make upsigue funcionando como antes. El stack de Compose ahora bloquea automáticamente las aplicaciones hasta que se completen los nuevos servicios de migración de ejecución única.
Páginas relacionadas
- Instalación de Midaz: configuración local completa con
make up. - Actualización de Midaz: flujos de actualización para local y Helm.
- Estrategias de despliegue: resumen del despliegue en BYOC.
- Variables de entorno de Tracer: referencia completa de configuración de Tracer.

