Docker e Kubernetes sono da sempre tra i termini più diffusi nel vocabolario dello sviluppo cloud native, in particolare quando si parla di container. Si tratta di tecnologie open source che consentono di facilitare l’intero ciclo di vita dei container, aggiungendo funzioni rispetto alle tecnologie di base, oltre a consentire un’interfaccia più semplice con gli utenti.
In questo semplice approfondimento ci soffermeremo in particolar modo sul mondo di Docker, per capire innanzitutto cosa sia, da dove provenga, cosa lo differenzia dal container Linux tradizionale, oltre a comprendere le ragioni del suo straordinario successo, che lo ha reso a tutti gli effetti uno standard di riferimento a livello tecnologico.
Cos’è Docker
Docker è una piattaforma software open source, sviluppata dall’omonima azienda, che permette di creare, testare e distribuire applicazioni containerizzate. Docker esegue infatti il software in unità standardizzate: i container, ambienti che offrono tutto il necessario per l’esecuzione: librerie, strumenti di sistema, codice e runtime.
L’obiettivo di Docker è pertanto quello di facilitare la creazione e la gestione dei container, ai fini di distribuire e calibrare le risorse per un’applicazione in qualsiasi ambiente, mantenendo sempre sotto controllo il codice eseguito.
I contenitori Docker possono essere eseguiti ovunque, nei data center on-premise o nel cloud pubblico e privato. Grazie alla virtualizzazione a livello del sistema operativo, tipico di questa tecnologia, Docker consente di creare container in modo nativo sia in ambienti Linux che per Windows.
Occorre tuttavia tenere sempre presente che le immagini Windows possono essere eseguite soltanto su installazioni Docker su host Windows, mentre le immagini Linux possono essere eseguite in host Linux, anche se mediante l’utilizzo di tecnologie di terze parti è possibile lanciarle anche su Windows.
La breve storia di Docker
Docker fa il suo primo annuncio sulla scena IT nel marzo del 2013, come piattaforma open source ai tempi nota come dotCloud. L’anno seguente è stata rilasciata la prima versione di Docker Engine 1.0 mentre nel 2016 è la volta di Swarm, lo strumento dedicato all’orchestrazione dei container Docker, che fa la sua comparsa nella versione 1.12.
Swarm aveva per certi versi le ambizioni di diventare un punto di riferimento nel mondo del container-as-a-service, ma in questo frangente abbiamo assistito alla netta prevalenza di Kubernetes, un’altra tecnologia open source, più complessa nell’insieme, ma anche più completa a livello di funzioni e capace di adattarsi ad una maggior varietà di contesti operativi.
Nel 2017 fa il suo esordio Docker Enterprise, mentre nel 2019 Docker viene acquisita da Mirantis, che oltre ai prodotti ne rileva le proprietà intellettuali. Inizialmente intenzionata a chiudere Swarm in favore di Kubernetes, Mirantis ha in seguito rivisto la sua decisione, continuando a supportare le funzioni di Docker per entrambe le piattaforme di orchestrazione, compresa quella proprietaria.
A cosa serve
Per comprendere le finalità di una piattaforma come Docker è sufficiente focalizzarci sulla differenza tra i container Docker e i più generici container Linux. Docker serve principalmente a semplificare la costruzione e la gestione dei container rispetto alla condizione standard.
Pur basandosi sulla medesima tecnologia, ossia la LXC (LinuX Container), Docker mira infatti a garantire un’esperienza molto più evoluta rispetto all’implementazione standard. LXC consente di base una virtualizzazione leggera, indipendente dall’hardware sottostante, ma di base piuttosto acerba e macchinosa da implementare. In altri termini, LXC base presenta evidenti criticità in termini di user experience.
Docker lavora nello specifico su molti aspetti per facilitare l’interfaccia tra il container e l’utente finale, ad esempio attraverso una serie di procedure automatizzate che guidano step-by-step alla costruzione del container stesso, con un corretto versionamento di tutte le immagini create.
Docker cerca di facilitare anche gli aspetti legati alla suddivisione delle applicazioni da eseguire sui vari container, per rendere più pratica e veloce l’orchestrazione complessiva, soprattutto quando si ha a che fare con applicazioni composte da un numero di componenti molto elevato.
Differenze tra immagini Docker e container Docker
Nell’ampio lessico che fa riferimento alla tecnologia Docker, è bene evitare la confusione che potrebbe generarsi parlando di immagini Docker e container Docker. Non sono infatti la stessa cosa e la loro comprensione agevola la corretta contestualizzazione operativa della piattaforma.
Immagini Docker
L’immagine Docker contiene il codice dell’applicazione da eseguire e tutti le librerie e le dipendenze necessarie al codice per l’esecuzione come container. Sulla base di ciò, quando si esegue una immagine Docker, si generano di fatto una o più istanze del container.
Le immagini Docker sono formate da vari livelli e ad ognuno corrisponde una versione dell’immagine. L’ultimo livello corrisponde con la versione più recente, ma viene conservato uno stato delle versioni precedenti per ragioni di ripristino o favorire l’utilizzo in altri progetti. Questo spiega perché gli sviluppatori cerchino spesso le immagini Docker nei repository alimentati dalla community. Ovviamente da una singola immagine Docker è possibile crearne molte altre e il punto di partenza corrisponderà ai medesimi elementi in comune.
Container Docker
Nella struttura dell’immagine Docker, il container si configura semplicemente come un livello specifico, denominato livello container. Le modifiche a livello di container, come l’aggiunta e l’eliminazione di file, vengono salvate soltanto nel livello container, nel momento stesso in cui questo è in esecuzione, senza influenzare l’immagine di base, che può essere utilizzata per avviare più istanze container contemporaneamente.
Dovendo dare una definizione, i container Docker sono pertanto delle istanze dal vivo delle immagini Docker. Seguendo questa logica, ci risulta più semplice comprendere come le immagini Docker siano costituite da file in sola lettura, mentre il container Docker caratterizza la parte editabile a tutti gli effetti.
Quando utilizzare Docker
Docker costituisce una valida alternativa quando si tratta di utilizzare i container nei progetti di sviluppo. Le ragioni per utilizzarlo sono quindi strettamente connesse all’utilità dei cointainer stessi, strumenti ormai irrinunciabili per sviluppare software basato su un’architettura a microservizi. In particolare questo vale per quanto concerne le metodologie DevOps impiegate per lo sviluppo di applicazioni cloud native, che prevedono continui cicli CI / CD (continous integration / continous deploy), per garantire all’utente finale sempre e soltanto la versione più aggiornata.
La tecnologia alla base dei container, e pertanto dello stesso Docker, può essere estremamente sintetizzata in tre termini chiave:
- Builder: strumenti utilizzati per creare i container. Nel caso di Docker, tale tool corrisponde a Dockerfile;
- Engine: è il motore che consente di eseguire i container, come nel caso di Docker command e Dockerd Daemon;
- Orchestrazione: tecnologia utilizzata per gestire i container, con la completa visibilità in merito al loro stato di esecuzione (attività, server / VM, ecc.), come nel caso di Docker Swarm o del celebre Kubernetes.
Il vantaggio fondamentale di un container consiste nel rendere disponibile sia l’applicazione che la configurazione dell’ambiente di esecuzione. Questo consente di gestire le varie immagini come istanze, senza dover installare ogni volta l’applicazione, come avveniva nel caso delle procedure tradizionali.
Questa caratteristica si lega ad evoluzioni sempre più raffinate, fondate sulla loro natura effimera, che consente di avviare e cessare il container senza soluzione di continuità, esclusivamente in funzione dei carichi di lavoro che lo richiedono.
Se si verifica un’anomalia, come un arresto anomalo o, caso più comune, il container non si rende più necessario perché l’applicazione che esegue ha nel frattempo cessato la propria attività, è ad esempio possibile orchestrare la sua chiusura in funzione di determinati parametri di contesto, senza dover costringere un sistemista ad eseguire manualmente ogni procedura.
Piattaforme come Docker e Kubernetes consentono di creare una pipeline end-to-end nella gestione del ciclo di vita delle applicazioni cointainerizzate, generando un elevato valore aggiunto grazie al livello di automatizzazione che consentono di raggiungere.
Perché utilizzare Docker
Nonostante un’età relativamente giovane, Docker è diventato un vero e proprio punto di riferimento, al punto che, in modo piuttosto improprio, viene spesso impiegato quale sinonimo di container, a cui andrebbe riconosciuta una connotazione ben più ampia, se si considera che LXC è stato implementato nel kernel Linux molto prima della nascita di Docker.
A livello funzionale, un eventuale problema di memoria corta in fatto di storia della tecnologia non costituisce comunque una criticità insormontabile. Quanto ci preme evidenziare sono i vantaggi pratici che una soluzione come Docker consente di ottenere ai suoi utilizzatori. Le stesse ragioni che li hanno convinti ad implementarlo nelle proprie pipeline di sviluppo. In questa sintesi finale riprenderemo pertanto anche alcuni degli aspetti elencati nel corso dei precedenti paragrafi.
Docker è attualmente utilizzato da milioni di sviluppatori in tutto il mondo e risulta disponibile nei principali ecosistemi cloud, con personalizzazioni che aiutano l’utente ad operare in maniera ancora più efficiente, soprattutto quando si tratta di combinare varie tecnologie e servizi.
Un consapevole impiego della piattaforma Docker consente soprattutto di estendere e migliorare l’impiego, anche su Windows Server, delle funzioni di containerizzazione standard di Linux, in particolare:
Granularità e maggior disaccoppiamento tra i processi
A differenza di LXC standard, Docker consente di eseguire un solo processo all’interno di un container. In questo modo si ottiene una struttura granulare che permette di ottenere una maggior resilienza funzionale, dal momento che un processo di manutenzione, aggiornamento o modifica implica un downtime circoscritto al processo interessato, senza ulteriori combinazioni.
Maggior portatilità dei container
I container Docker possono essere eseguiti, previa installazione della piattaforma, su qualsiasi sistema, purché rispetti i requisiti di host. Quindi non vi sono particolari restrizioni nello spostare nei data center on-premise e in cloud. I container LXC standard sono invece più schizzinosi in termini di configurazione specifiche delle macchine, fisiche o virtuali, su cui si prevede la loro esecuzione.
Versionamento dei container
Grazie alla struttura nativa a livelli, Docker conserva la cronologia delle immagini, in modo da poter risalire in qualsiasi momento a differenti versioni. Al di là del vantaggio intrinseco, ciò consente di abilitare diverse funzioni molto interessanti, come quella che consente di adottare soltanto le variazioni tra due differenti versioni.
Automatizzazione della creazione di container
Docker dispone di vari tool per consentire una rapida costruzione del container sulla base di preset e procedure ad alto livello di automatizzazione, orientate al tipico self service dei servizi in cloud.
Repository e condivisione di risorse
Grazie ad una enorme community, che si arricchisce progressivamente di partecipanti, gli utenti di Docker possono avere a disposizione moltissime immagini messe a disposizione sui principali repository impiegati dagli sviluppatori. Ciò agevola moltissimo soprattutto la fase di avvio dei progetti di sviluppo, ogni volta che si profila l’esigenza di dare vita ad una nuova funzione.
Riutilizzo dei container per diverse applicazioni
In totale coerenza con il disaccoppiamento su cui si basa l’architettura a microservizi, le immagini Docker possono essere riutilizzate in progetti differenti, quali template per avviare nuove istanze containerizzate.