Tu microservicio no arranca en local
Un microservicio que no levanta en tu máquina casi nunca es un fallo de tu código. Es una de seis cosas, y la mayor parte del tiempo perdido se va en no saber cuál de las seis. Esta página las ordena por frecuencia y da la comprobación que descarta cada una en menos de un minuto.
El orden importa: descarta de fuera hacia dentro
La tentación es abrir el código. Casi siempre es lo último que hay que mirar, porque el mismo commit arranca en el entorno compartido. Lo que ha cambiado no es el servicio: es lo que tiene alrededor.
| # | Causa | Qué verás | Comprobación |
|---|---|---|---|
| 1 | Puerto ocupado | address already in use, EADDRINUSE, o el proceso muere al instante |
lsof -i :8080 |
| 2 | Infraestructura caída | connection refused hacia el 5432, el 9092 o el 6379 |
docker ps |
| 3 | Arrancó antes de tiempo | Arranca a veces sí y a veces no, con el mismo código | Vuelve a lanzarlo a mano; si ahora va, era el orden |
| 4 | Configuración incompleta | Falla al construir un bean o al leer una propiedad | Compara las variables con las del entorno compartido |
| 5 | Base de datos sin esquema | relation … does not exist, o migraciones que fallan |
Conéctate a mano y lista las tablas |
| 6 | Versión del runtime | UnsupportedClassVersionError, sintaxis que no compila |
java -version, node -v |
1. El puerto ya está ocupado
Es la causa más frecuente y la que más rápido se descarta. Todos los proyectos de la misma tecnología traen el mismo puerto por defecto: el 8080 en JVM, el 3000 en Node, el 5432 en Postgres. Basta con tener dos cosas abiertas.
# macOS y Linux
lsof -i :8080
# Windows
netstat -ano | findstr :8080
Si sale algo, ya tienes el culpable. Lo incómodo no es matarlo: es que mañana vuelva a pasar con otro puerto, y que el servicio que lo llama siga apuntando al viejo.
2. La infraestructura no está levantada (o no está lista)
docker ps y mira si están Kafka, Redis y Postgres. Pero cuidado con la
trampa: «levantado» no es «listo». Un contenedor tiene PID desde el
primer segundo, y el Postgres de dentro puede tardar otros veinte en aceptar
conexiones. Si tu servicio arranca en ese hueco, ve un connection refused y
se muere.
Es exactamente lo que depends_on de compose no resuelve: espera al
contenedor, no al servicio. Por eso hace falta un healthcheck y una
condición service_healthy, y por eso el mismo compose arranca en una máquina
rápida y no en una lenta.
3. Arrancó antes que aquello a lo que llama
El síntoma que lo delata: a veces arranca y a veces no, con el mismo código. Eso es una carrera, no un error. Tu servicio se registra o pide algo al arrancar, y quien se lo tiene que dar todavía no estaba respondiendo.
Lanzarlo otra vez a mano lo confirma en diez segundos: si ahora va, no era el código.
4. Le falta configuración que en la nube alguien le da
En el entorno compartido, esas variables las pone el despliegue. En tu máquina las pones tú, y el problema no es ponerlas: es saber cuáles. La lista suele vivir en un fichero de despliegue que no está en tu repositorio.
El error se reconoce porque el servicio muere construyendo, no sirviendo: un bean que no se puede crear, una propiedad obligatoria que falta, un cliente que no encuentra su URL base.
5. La base de datos existe pero está vacía
Contenedor arriba, conexión correcta, y aun así relation "orders" does not
exist. Falta correr las migraciones, o han corrido contra otra base.
La regla que conviene no romper mientras persigues esto: no lances migraciones
contra el entorno compartido. Un flyway migrate disparado sin
querer contra la base común es una tarde perdida para todo el equipo, no solo para ti.
6. La versión del runtime no es la que espera el proyecto
La última de la lista porque es la menos frecuente, pero la que más despista cuando pasa:
el mensaje habla de clases o de sintaxis y parece un problema de código. Si el proyecto
declara su versión (.sdkmanrc, .nvmrc, la propiedad de Maven),
compárala con la que tienes.
Y cuando arranca, empieza el problema de verdad
Las seis causas de arriba son de un servicio. Cuando arrancan tres y tienen que
hablarse, aparece la que no está en ninguna lista: a dónde llama cada uno.
La URL correcta depende de dónde corre quien llama —un proceso nativo llega a un
contenedor por localhost, un contenedor llega a otro por el nombre del
servicio, y un contenedor que llama a algo nativo necesita el nombre especial del host—,
así que la misma dependencia tiene tres URLs según cómo esté corriendo cada extremo.
Eso es lo que acaba escrito a mano en la configuración de un repositorio que no es tuyo, con la nota mental de no comitearlo.
Cómo lo quita Aseptic de en medio
Aseptic no adivina por qué falla tu código, y esta página no lo vende como tal. Lo que hace es que cinco de las seis causas dejen de ocurrir:
- Los puertos que chocan se remapean solos, y el valor nuevo es el que reciben los que llaman — no hay que avisar a nadie.
- La infraestructura la levanta la app y espera a que esté sana, no a que tenga PID.
- El escenario arranca en orden de dependencia, esperando la salud de cada uno antes de seguir.
- La configuración se inyecta al arrancar como propiedades
-Do variables de entorno, así que no hay fichero que editar ni que acordarse de revertir. - Las URLs entre servicios se reescriben con la perspectiva correcta según dónde corra cada extremo.
La sexta —la versión del runtime— sigue siendo tuya, y así debe ser: es tu proyecto el que declara con qué se construye.
Si esto te pasa a diario, el punto de partida es qué necesita un entorno local de microservicios, y de ahí levantar solo la parte que te interesa.
Preguntas frecuentes
¿Por qué mi microservicio arranca en el entorno compartido y no en mi máquina?
Casi siempre porque en el entorno compartido alguien resolvió por ti las cuatro cosas que en local resuelves tú: la infraestructura, el orden de arranque, las URLs entre servicios y los datos. El servicio no ha cambiado; ha cambiado lo que tiene alrededor.
El log dice «connection refused» pero el contenedor está levantado. ¿Por qué?
Porque «levantado» no es «listo». Un contenedor tiene PID desde el primer segundo y su servicio puede tardar veinte más en aceptar conexiones. depends_on de compose espera al contenedor, no a la salud.
¿Cómo sé si el problema es el puerto?
Mira quién lo tiene: lsof -i :8080 en macOS o Linux, netstat -ano | findstr :8080 en Windows. Si sale algo, el error no es de tu código.
¿Merece la pena arreglar esto o vivir con el LOCAL_SETUP.md?
Depende de cuántas veces al día lo pagues. Un documento de cuarenta pasos cuesta poco de escribir y mucho de mantener: falla distinto en cada máquina y nadie lo actualiza cuando cambia un flag.