Come avviare un ambiente di microservizi in locale
Avviare un microservizio in locale è facile: lo dice il suo README. I problemi cominciano quando il flusso che vuoi provare ne attraversa quattro, e ognuno ne chiama altri due che non sono tuoi.
Questa pagina non è il tutorial di uno strumento specifico: è quali pezzi servono, perché la parte difficile non è quella che sembra, e come si risolve ciascuna — con Aseptic alla fine, perché è ciò che questo sito documenta, ma i quattro problemi sono gli stessi qualunque cosa tu usi.
I quattro pezzi
Sezione intitolata “I quattro pezzi”Un ambiente locale che serva a qualcosa deve risolvere quattro cose. In questo ordine di difficoltà reale, che quasi mai è l’ordine con cui le si affronta:
- Infrastruttura comune. Kafka, Redis, PostgreSQL, quello che usa il tuo sistema. È la parte più visibile e la più risolta: i container.
- Avvio di ogni servizio. Il suo comando, il suo profilo, le sue variabili, la sua porta. Lavoro ripetitivo, ma meccanico.
- Comunicazione fra i servizi. Dove chiama ciascuno. È qui che se ne va la mattina, ed è ciò di cui quasi nessuno parla.
- Dati. Uno schema creato e qualcosa dentro con cui provare.
1. L’infrastruttura
Sezione intitolata “1. L’infrastruttura”Un docker-compose.yml con i pezzi comuni e docker compose up. È ciò che fanno tutti ed
è giusto: i container sono esattamente lo strumento adatto per questo.
Due dettagli che mordono più tardi:
- Le porte collidono. Ogni team dichiara la 5432 e la 6379. Appena hai due progetti aperti, o alzi e abbassi, cominciano i conflitti.
- L’infrastruttura si condivide fra progetti, i dati no. Riutilizzare lo stesso Postgres per due sistemi diversi finisce in uno schema di cui nessuno sa di chi sia.
2. L’avvio di ogni servizio
Sezione intitolata “2. L’avvio di ogni servizio”Ogni servizio ha il suo modo: ./mvnw quarkus:dev,
./gradlew bootRun -Dspring.profiles.active=local, npm start, un binario. Con profili,
variabili e flag diversi.
È questo che di solito finisce scritto in un LOCAL_SETUP.md di quaranta passi: funziona,
ma invecchia male. Nessuno aggiorna il documento quando cambia una flag, e chi arriva dopo
scopre lo scarto a suon di errori.
Un dettaglio che decide molto più di quanto sembri: non tutti i servizi vogliono girare allo stesso modo. Quello su cui stai lavorando lo vuoi nativo, con hot reload e con il debugger agganciato. Gli altri tre devono solo essere su: in container vanno benissimo, isolati e senza sporcarti la macchina.
3. La comunicazione: la parte difficile
Sezione intitolata “3. La comunicazione: la parte difficile”Qui c’è il lavoro vero, ed è quello che nessuno strumento di container ti risolve.
Il tuo servizio bff chiama orders. In produzione quell’URL lo dà la service discovery o
l’ingress. In locale, qualcuno deve decidere dove punta, e le opzioni non sono
equivalenti:
- Al servizio avviato sulla tua macchina. È quello che vuoi quando stai cambiando entrambi i lati. Ma allora devi avviarlo anche lui, con tutta la sua coda di dipendenze dietro.
- All’ambiente condiviso di sviluppo. Ti risparmia di avviarlo, in cambio di una connessione alla sua rete, di dati che cambiano sotto i tuoi piedi e del fatto che se quell’ambiente è giù, lo sei anche tu.
- A un mock. Perfetto quando la risposta di quel servizio ti è indifferente, o quando non riesci nemmeno a raggiungerlo. In cambio di mantenere lo stub.
Quello che costa non è scegliere: è applicare la scelta. Ogni opzione significa cambiare un URL nella configurazione di un repository che non è tuo, ricordarti di non committarlo, e disfarlo quando vuoi provare altro. Moltiplica per servizi e per volte al giorno.
E c’è una trappola: l’URL corretto dipende da dove gira chi chiama. Un servizio nativo
raggiunge un container tramite localhost:porta; un container che ne chiama un altro,
tramite il nome del servizio; e un container che chiama qualcosa di nativo sulla tua
macchina ha bisogno del nome speciale dell’host. La stessa dipendenza, tre URL diversi a
seconda di come sta girando ciascun estremo.
4. I dati
Sezione intitolata “4. I dati”Schema creato, migrazioni eseguite e qualche dato minimo. Di solito si risolve con le migrazioni dell’applicazione stessa più uno script di seed.
La regola che conviene non infrangere: l’ambiente locale non tocca database condivisi. Una migrazione lanciata per sbaglio contro l’ambiente di sviluppo comune è un pomeriggio perso per tutto il team.
I modi per montarlo
Sezione intitolata “I modi per montarlo”| Approccio | Buono per | Dove resta corto |
|---|---|---|
docker-compose di tutto |
Infrastruttura; un sistema piccolo e stabile | Costruire l’immagine del tuo servizio a ogni modifica; niente hot reload né debugger comodi; la comunicazione resta configurazione a mano |
Script + LOCAL_SETUP.md |
Partire in fretta | Invecchia: nessuno lo aggiorna e fallisce in modo diverso su ogni macchina |
| Testcontainers | Test di integrazione veri | L’ambiente nasce e muore con il test; non è un posto dove lavorare |
| Kubernetes locale (Kind, minikube) | Somigliare alla produzione | Tanta macchina e tanto ciclo di build per il quotidiano; il ciclo di modifica si allunga |
| Orchestratore locale | Il ciclo quotidiano con più servizi | Bisogna descrivere ogni servizio una volta |
Nessuno è sciocco: risolvono cose diverse e spesso convivono. Ciò che nessuno dei primi quattro fa è decidere per dipendenza dove chiama ogni servizio e applicarlo senza toccare i repository.
Come lo risolve Aseptic
Sezione intitolata “Come lo risolve Aseptic”Aseptic è un orchestratore desktop che si occupa dei quattro pezzi, e tratta il terzo come il problema principale che è.
- Descrivi ogni servizio una volta. Punti alla cartella del repository e la sua tecnologia, le sue porte, l’infrastruttura di cui ha bisogno e chi chiama vengono rilevati in automatico. Rivedi e basta.
- Raggruppi in uno scenario i servizi di un flusso — «Checkout», «Registrazione cliente» — e si avviano insieme, in ordine e aspettando che ciascuno sia sano.
- Per ogni dipendenza scegli locale, cloud o mock, e il motore
riscrive l’URL all’avvio iniettandolo come configurazione
—flag
-Do variabili d’ambiente—, con la prospettiva giusta a seconda di dove gira ciascun estremo. I tuoi repository non si toccano. - L’infrastruttura comune (Kafka, Redis, PostgreSQL) la gestisce l’app in Docker, con rimappatura automatica delle porte quando collidono.
- Ogni servizio, nativo o in container, a tua scelta: nativo quello su cui stai lavorando, in container quelli di sfondo.
E quello che monti si condivide: uno scenario si esporta in un file autonomo, così chi
arriva clona, importa e avvia invece di leggersi il LOCAL_SETUP.md.
Cominciare
Sezione intitolata “Cominciare”- Installare Aseptic — è gratis e ti serve solo Docker.
- Il tuo primo scenario in 5 minuti — i passi concreti.
- Mockare una dipendenza — se quello che ti blocca oggi è non avere connessione al cloud.