C'è una terza via, come hai detto tu stesso. Penso che tu stia confondendo sviluppo, test e implementazione. Propongo che l'intero SDLC sia considerato nel suo complesso, in primo luogo, per capire che cosa stai cercando di ottenere. Questo è un grande argomento, ma farò del mio meglio per riassumere.
TL; DR;
In breve, è necessario separare:
- il tuo codice, da
- la configurazione dell'applicazione, da
- la configurazione dell'ambiente di sistema.
Ciascuno deve essere indipendente l'uno dall'altro e opportunamente:
- versione controllata
- testato
- schierabili
Versione più lunga
Per prima cosa, hai un'applicazione composta da codice e configurazione (separata di serie). Questo deve essere testato, sia per la build che per la funzione intenzionale: si chiama integrazione continua (CI). Esistono molti provider di questo servizio sia online che localmente, ad esempio CircleCI per un provider cloud che si collega al repository e crea e verifica ogni volta che si esegue il commit. Se il tuo repository è on-prem e non puoi utilizzare un provider cloud, qualcosa come Jenkins sarebbe equivalente. Se la tua applicazione è abbastanza standard, probabilmente esiste un'immagine Docker esistente che può essere utilizzata dal servizio CI. In caso contrario, sarà necessario crearne uno, o un cluster, in modo da poter distribuire il codice dell'applicazione e la configurazione. Correttamente configurato, avrai una vasta gamma di statistiche sulla qualità del tuo codice applicazione.
Successivamente, una volta che sei soddisfatto della funzionalità e della correttezza della tua applicazione, il codebase dovrebbe essere opportunamente taggato per una specifica release. Questa build dovrebbe quindi essere distribuita in un ambiente di test. Si noti che il codice sarà lo stesso testato nell'IC (in modo simile, se è stato eseguito correttamente), ma la configurazione potrebbe essere diversa. Anche in questo caso alcuni fornitori di CI possono offrire questo passaggio per testare la distribuzione di un'applicazione pacchettizzata e una configurazione discreta. Questa fase includerà tipicamente test funzionali dell'utente (per nuove funzionalità) e test automatici (per funzionalità conosciute). Se la versione supera questa fase, hai un candidato alla release per i test di integrazione. Puoi eseguire i test di automazione da un altro contenitore Docker, a seconda della tua applicazione questi possono essere grandi ed elaborati come la tua stessa applicazione - infatti, ci sono alcune metriche che dichiarano lo sforzo di test sono 1: 1 per lo sforzo di codifica (anche se non sono sicuro su questo me stesso).
Penultimo, il prossimo passo è dove costruisci il tuo ambiente (di sistema) come se fosse una produzione. Se stai usando Docker in produzione, è qui che penserai al rafforzamento della sicurezza, all'ottimizzazione della rete e del server, ecc. Le immagini Docker potrebbero essere basate su quelle che hai utilizzato nello sviluppo (idealmente), ma potrebbero esserci dei cambiamenti per il ridimensionamento e la sicurezza , come ho detto. Ormai i test funzionali dell'applicazione dovrebbero essere completi, si è più interessati alla sicurezza e alle prestazioni. Come da test funzionale, i tuoi test qui possono essere sviluppati, implementati ed eseguiti da altre immagini Docker. Questo passaggio era orribilmente costoso e raramente fatto in modo da aver bisogno di hardware dedicato che riproducesse la produzione. Oggi, questo è completamente fattibile in quanto puoi alzarti e demolire l'intero ambiente di quasi tutte le scale su richiesta.
Infine, hai un rilascio che dovrebbe essere pronto per la produzione con solo un piccolo set di delta di configurazione da quello del test di integrazione (indirizzi IP, URI del database, password ecc.) Il tuo codice base è stato testato almeno in tre diversi ambienti a questo punto e la maggior parte della configurazione del sistema almeno una volta.