Guida ai contenitori Linux: un'introduzione ai contenitori

Container è una parola d'ordine da anni... ma cosa sono esattamente?

I contenitori sono un metodo per eseguire applicazioni virtualizzate sul computer, simile alle macchine virtuali, ma che utilizza un insieme diverso di tecnologie sottostanti. Possono essere complessi da comprendere, ma sono essenziali per gestire tutto Minecraft server di Google. E ti mostreremo come configurarli.

Utilizzeremo Linux, un sistema operativo costruito con particolare attenzione alla portabilità, alla modularità e alla stabilità. Linux è ovunque, dai server ai microonde alle console per videogiochi. I contenitori non si limitano a funzionare su Linux, ma le tecnologie alla base di essi sono più adatte e funzionano meglio su Linux. Se sei nuovo su Linux, ti consigliamo di dare un'occhiata al nostro guida per principianti prima di tuffarsi.

I container sono macchine virtuali?

I contenitori possono essere un argomento complesso, ma è meglio iniziare con un punto chiave: un contenitore lo è non una macchina virtuale. Una macchina virtuale è una versione simulata di un hardware specifico e del relativo software eseguita in un cosiddetto hypervisor. Se hai mai utilizzato software come VirtualBox o

multipassaggio, allora hai utilizzato un hypervisor.

L'hypervisor di solito viene eseguito come proprio sistema operativo (noto come hypervisor di tipo 1) o all'interno dei confini di un altro sistema operativo come Windows o Ubuntu (un hypervisor di tipo 2). La responsabilità dell'hypervisor è presentare al sistema operativo guest l'hardware simulato necessario per l'esecuzione. L'intero sistema operativo può quindi essere eseguito sopra. Ciò include qualsiasi cosa, da una CPU e RAM simulate a bus dati, unità disco o adattatori di rete. Questa simulazione è computazionalmente costosa, quindi le macchine virtuali in genere hanno un sovraccarico significativo.

Allora, cos'è un contenitore?

Un contenitore è simile a una macchina virtuale in quanto contiene ed esegue software in un ambiente isolato su un sistema host. Tuttavia, i contenitori sostituiscono la tradizionale virtualizzazione dell’hardware facendo affidamento direttamente sul sistema operativo host. I contenitori condividono le librerie e i file binari del sistema operativo host e dispongono solo delle risorse e delle dipendenze necessarie per eseguire l'applicazione specifica che contengono. Ciò significa che non è necessario un sistema operativo completo per contenitore, poiché tutti i contenitori in esecuzione su a system può condividere il singolo sistema operativo host mantenendo la segregazione ottenuta con virtual macchine.

I contenitori accedono al sistema operativo host tramite un motore di contenitori, che gestisce i contenitori in esecuzione e ne controlla l'accesso al sistema operativo sottostante. Ciò potrebbe includere l'applicazione della sicurezza tra i contenitori e la concessione o la negazione dell'accesso ai file del sistema operativo o alle connessioni di rete.

Quali sono alcuni compromessi per l'utilizzo dei contenitori?

Sebbene le macchine virtuali e i contenitori siano simili, l'utilizzo dei contenitori presenta i suoi svantaggi. Innanzitutto, le macchine virtuali sono considerate più sicure, poiché la superficie di attacco per "sfuggire" alla macchina virtuale è significativamente più piccola e più difficile da penetrare. Un contenitore potrebbe ad esempio non essere adatto per testare malware.

Il vantaggio principale dell'utilizzo dei contenitori è che sono leggeri, evitando la necessità di virtualizzare un intero sistema operativo significa tempi di avvio minimi e riduzione del sovraccarico del sistema. Ciò significa che su un host possono essere eseguiti molti più contenitori, cosa che non sarebbe possibile con le macchine virtuali.

Poiché i contenitori non richiedono un sistema operativo completo, possono essere facilmente raggruppati in immagini più piccole e distribuiti. Mentre l'immagine completa di una macchina virtuale potrebbe facilmente essere di decine di gigabyte, i contenitori possono arrivare in immagini fino a 15 KB. Ciò rende estremamente semplice la distribuzione e l'utilizzo dei contenitori. Lo dimostreremo eseguendo alcuni semplici contenitori di esempio in Docker.

Installazione di Docker

È molta teoria, quindi passiamo alla pratica. Per mostrarti come configurare un contenitore, installeremo Docker in Ubuntu 23.10 e lo utilizzeremo per eseguire un semplice contenitore Hello World. I nostri passaggi sono testati su una macchina virtuale, ma puoi anche eseguire il dual-boot dal tuo PC Windows o utilizzare un file ottimo portatile per Linux.

Docker è rapidamente diventato lo strumento di containerizzazione di fatto. Sebbene esistano altri strumenti, Docker è ampiamente adottato ed è perfetto per tutte le applicazioni tranne quelle più impegnative. C'è documentazione sulle diverse modalità di installazione di Docker, ma utilizzeremo lo script di installazione conveniente. Questo comando scaricherà uno script da get.docker.com sul tuo computer locale:

$ curl -fsSL https://get.docker.com -o get-docker.sh

È quindi possibile eseguire questo script per installare Docker. Puoi verificare che Docker sia installato correttamente controllando la versione con:

$ sudo sh ./get-docker.sh

Seguito da un controllo della versione con:

$ sudo docker version

Puoi anche verificare che il servizio docker sia in esecuzione in background con:

$ sudo systemctl status docker

Dovrebbe indicare "attivo (in esecuzione)" in testo verde, come evidenziato nello screenshot qui sotto. Anche la versione del motore Docker dovrebbe essere stampata senza errori.

Facendo un semplice esempio

Ora che Docker è installato, puoi utilizzarlo per scaricare un'immagine del contenitore. Le immagini dei contenitori sono molto simili agli ISO per le macchine virtuali, tranne per il fatto che sono solitamente più piccole e più facili da creare. Scarica una semplice immagine del contenitore Hello-World con il seguente comando:

$ sudo docker pull hello-world

Una volta scaricata l'immagine, puoi verificarla elencando le immagini scaricate sul tuo sistema utilizzando quanto segue:

$ sudo docker images

Ora dovresti vedere hello-world scaricato. Notate le dimensioni molto ridotte (13Kb sulla nostra macchina di prova), così come il suo tag. Il tag di un'immagine è effettivamente la sua versione. Per impostazione predefinita, Docker scaricherà la versione più recente di un'immagine. Esegui un contenitore basato su questa immagine utilizzando:

$ sudo docker run hello-world: latest

Questo produrrà il discorso del ciao mondo di Dockers, che viene eseguito da un programma C molto piccolo (che puoi controllare su GitHub).

Congratulazioni; hai eseguito il tuo primo contenitore! In questo caso, il programma ha restituito il risultato e ha terminato la sua esecuzione. Il contenitore ora è morto e non funziona più.

Come mantenere in vita i contenitori

Dopo aver eseguito un contenitore di base, ora possiamo creare un esempio più complesso che non esce immediatamente una volta completata un'attività. I contenitori sono spesso costruiti attorno a un singolo processo, che può generare più processi. Una volta terminato questo processo di base, l'intero contenitore uscirà con esso. Potrebbe sembrare una limitazione, ma in realtà è molto simile al funzionamento dei sistemi init nell'intero kernel Linux.

Per eseguire un esempio persistente, possiamo estrarre un'immagine per Nginx, che è un server Web utilizzato per ospitare una percentuale significativa dei siti Web del mondo. Abbiamo scelto Nginx per questo esempio perché è semplice, non richiede configurazioni avanzate ed è leggero. Scarica l'ultima immagine Nginx con il seguente comando:

$ sudo docker pull nginx

Abbiamo aggiunto il -P flag qui per configurare il port forwarding dal contenitore al sistema operativo host. La porta 80 viene utilizzata per il traffico HTTP (ovvero web) non crittografato. Ciò ti consentirà di accedere al contenitore dal tuo computer host:

$ sudo docker run -p 80:80 nginx

Questo comando verrà eseguito nel tuo terminale in modalità collegata, il che significa che il contenitore è letteralmente collegato al tuo terminale, quindi tutti i log del contenitore verranno stampati lì. Una volta avviato il contenitore, aprirlo http://localhost nel tuo browser web. Vedrai una schermata di benvenuto di Nginx simile alla seguente:

Il contenitore Nginx è ora in esecuzione all'interno del motore del contenitore. Mentre Nginx viene eseguito in modalità collegata, continuerà a funzionare solo finché sarà aperto. È possibile uscire dal contenitore Nginx premendo CTRL+C nel tuo terminale.

Come eseguire i contenitori in background

Per eseguire Nginx in background, aggiungeremo un altro flag, -D, per la modalità distaccata. Questo avvierà il contenitore staccato dal tuo terminale, il che significa che è in background. Per esempio:

$ sudo docker run -d -p 80:80 nginx

È possibile elencare i contenitori in esecuzione su un sistema. Nota come il tuo contenitore Nginx è ora in esecuzione in background e gli è stato assegnato un ID.

$ sudo docker ps

Un contenitore in background in esecuzione può essere terminato utilizzando il suo ID. Potresti anche notare che al contenitore è stato assegnato un nome. Quando non ne viene specificato uno, Docker assegnerà a ciascun contenitore un nome casuale e univoco.

$ sudo docker kill 

Tuttavia, potresti testarlo con alcune immagini più interessanti. Ce ne sono molti disponibili al Hub Docker, che funziona come archivio centrale per le immagini del contenitore pubblico.

Immergersi più in profondità con i contenitori

Questa è stata una breve introduzione ai contenitori. I contenitori possono essere infinitamente complessi, ma sono un elemento fondamentale dei sistemi altamente distribuiti che gestiscono gran parte della nostra moderna Internet. Tuttavia, questo potere non impedisce il loro utilizzo su scala più piccola. La familiarità con le nozioni di base sui contenitori e su Docker può essere la porta d'accesso per l'esecuzione di servizi locali utili come a Server Minecraft o Plex su un vecchio PC.