Container Docker

Negli ultimi dieci anni, la soluzione di virtualizzazione Docker ha alterato drasticamente il modo in cui un software è costruito, distribuito e gestito. A differenza dei suoi predecessori, le macchine virtuali (VM), Docker virtualizza le singole applicazioni. Quindi, un container Docker è un container di applicazioni o software.

Il termine “container software” si basa sui container fisici, come quelli usati sulle navi. Nella logistica, i container come unità standardizzate sono ciò che ha reso possibile le moderne catene di vendita al dettaglio. Un container può essere trasportato su qualsiasi nave, camion o treno progettato per questo scopo. Ciò in buona parte funziona indipendentemente dal contenuto del container. All’esterno, il container è dotato di interfacce standardizzate. Nel caso dei container Docker accade qualcosa di molto simile.

Registra il tuo dominio
  • Certificato SSL Wildcard incluso
  • Registrazione di dominio sicura
  • Indirizzo e-mail professionale da 2 GB

Cos’è un container Docker?

Cos’è esattamente un container Docker? Sentiamo cosa hanno da dire gli sviluppatori Docker in merito:

Citazione

“Containers are a standardized unit of software that allows developers to isolate their app from its environment.“ – Fonte: https://www.docker.com/why-docker

“I container sono un’unità di software standardizzata che permette agli sviluppatori di isolare un’applicazione dal proprio ambiente.” (Traduzione: IONOS)

A differenza di un container fisico, un container Docker esiste in un ambiente virtuale. Un container fisico è assemblato sulla base di una specifica standardizzata. Per i container virtuali il processo di creazione è molto simile. Un container Docker è infatti creato da un modello immutabile chiamato “immagine”. Un’immagine Docker contiene le dipendenze e le impostazioni di configurazione necessarie per creare un container.

Proprio come molti container fisici possono derivare da una singola specifica, un qualsiasi numero di container Docker può essere creato da una singola immagine. I container Docker costituiscono quindi la base per i servizi scalabili e gli ambienti riproducibili per lo sviluppo di applicazioni. Possiamo creare un container da un’immagine e anche salvare un container esistente in una nuova immagine. È inoltre possibile eseguire, mettere in pausa e fermare i processi all’interno di un container.

A differenza della virtualizzazione basata su macchina virtuale (VM), un container Docker non contiene il proprio sistema operativo (OS, “Operating System”) ma tutti i container in esecuzione su un host Docker accedono allo stesso kernel OS. Quando Docker viene distribuito su un host Linux, viene utilizzato il kernel Linux esistente. Se il software Docker viene eseguito su un sistema non-Linux, viene utilizzata un’immagine minima del sistema Linux tramite un hypervisor o una macchina virtuale.

A ogni container viene assegnata una certa quantità di risorse di sistema al momento dell’esecuzione la quale include RAM, core della CPU, memoria di massa e dispositivi di rete (virtuali). Tecnicamente, i “cgroups” (abbreviazione di “control groups”) limitano l’accesso di un container Docker alle risorse di sistema. I “kernel namespaces” sono utilizzati per dividere le risorse del kernel e distinguere i processi l’uno dall’altro.

Esternamente, i container Docker comunicano tramite la rete. Per fare ciò, dei servizi specifici si occupano della scansione delle porte esposte. Questi sono di solito dei server web o database. I container stessi sono controllati sul rispettivo host Docker tramite l’API Docker e possono essere avviati, fermati e rimossi. Il client Docker fornisce un’interfaccia a riga di comando (CLI) con i comandi appropriati per ognuna di queste operazioni.

Qual è la differenza tra i container e le immagini Docker?

I termini “container Docker” e “immagine Docker” causano spesso confusione. Questo non sorprende dato che è un po’ come il paradosso dell’uovo e della gallina: un container viene creato da un’immagine; tuttavia, un container può anche essere salvato come una nuova immagine. Diamo un’occhiata alle differenze tra i due concetti in dettaglio.

Un’immagine Docker è un modello inerte. L’immagine occupa solo uno spazio minimo su un disco rigido e non fa altro. Al contrario, il container Docker è un’istanza “vivente”. Un container Docker in esecuzione ha un comportamento, interagisce con l’ambiente. Inoltre, un container ha uno stato che cambia nel tempo, utilizzando una quantità variabile di RAM.

Probabilmente conoscete già i concetti di “classe” e “oggetto” della programmazione orientata agli oggetti (OOP). La relazione tra un container Docker e un’immagine Docker è simile alla relazione tra un oggetto e la sua classe associata. Una classe esiste solo una volta e può creare molti oggetti simili. La classe stessa viene caricata a partire da un file di codice sorgente. Nell’universo Docker viene adoperato un procedimento affine. Un modello viene creato da un’unità sorgente, un “Dockerfile”, che a sua volta crea molte istanze:

  Codice sorgente Modello Istanza
Concetto Docker Dockerfile Immagine Docker Container Docker
Analogia nella programmazione Codice sorgente di classe loaded class oggetto istanziato
Consiglio

In questo articolo ci riferiamo al container Docker come a una “istanza in esecuzione” dell’immagine associata. I termini “istanza” e “istanziare” sono astratti. Se riscontrate difficoltà nel comprenderli, vi consigliamo di usare un piccolo trucco mnemonico. Sostituite “istanziare” con “ritagliare” nella vostra mente. Anche se non vi è una relazione diretta tra le parole, esiste una forte corrispondenza tra i loro significati in termini informatici. Pensate al principio in questo modo: proprio come si usa una formina per ritagliare molti biscotti simili da un impasto, si istanziano molti oggetti simili da uno stesso modello. Quindi, istanziare sta a indicare il procedimento attraverso il quale un modello crea un oggetto.

Come viene costruito un container Docker?

Per capire come viene costruito un container Docker, può aiutare fare riferimento alla metodologia “twelve-factor app”. Questa è una raccolta di dodici principi fondamentali per la costruzione e il funzionamento di un software orientato ai servizi. Sia Docker che l’app a dodici fattori risalgono al 2011. L’app a dodici fattori aiuta gli sviluppatori a progettare applicazioni Software as a Service (Saas) secondo standard specifici. Questi includono:

  • Usare formati dichiarativi per l’automazione della configurazione per minimizzare tempi e costi per i nuovi sviluppatori che si uniscono al progetto;
  • Avere un contratto pulito con il sistema operativo sottostante, offrendo la massima portabilità tra gli ambienti di esecuzione;
  • Essere adatto alla distribuzione sulle piattaforme cloud moderne, ovviando alla necessità di server e amministrazione dei sistemi;
  • Minimizzare la divergenza tra sviluppo e produzione, permettendo il deployment continuo per la massima agilità;
  • Essere in grado di scalare senza cambiamenti significativi agli strumenti, all’architettura o alle pratiche di sviluppo.

La struttura di un container Docker si basa su questi stessi principi. Inoltre, un container Docker include i seguenti componenti, che esamineremo in dettaglio di seguito:

  1. Sistema operativo container e union file system
  2. Componenti software e configurazione
  3. Variabili d’ambiente e configurazione runtime
  4. Porte e volumi
  5. Processi e registri

Sistema operativo e union file system

A differenza di una macchina virtuale, un container Docker non contiene il proprio sistema operativo. Invece, tutti i container in esecuzione su un host Docker accedono a un kernel Linux condiviso. Nel container è incluso solo uno strato di esecuzione minimo. Questo di solito include un’implementazione della libreria standard C e una shell Linux per l’esecuzione dei processi. Di seguito vi mostriamo una panoramica dei componenti dell’immagine ufficiale “Alpine Linux”:

Kernel Linux Libreria standard C Comandi Unix
Dall’host Musl libc BusyBox

Un’immagine Docker consiste in una pila di livelli di file system di sola lettura. Un livello descrive le modifiche al file system nel livello sottostante. Usando uno speciale union file system come overlay2, i livelli sono sovrapposti e unificati in un’interfaccia coerente. Quando si crea un container Docker da un’immagine viene aggiunto un livello protetto da scrittura a un altro livello descrivibile. Tutte le modifiche fatte al file system vengono incorporate nel livello descrivibile usando la strategia “copy-on-write”.

Componenti software e di configurazione

A partire dal sistema operativo minimo del container, i componenti software aggiuntivi vengono installati su un container Docker. Questo è di solito seguito da ulteriori passaggi di impostazione e configurazione. Per l’installazione vengono utilizzati i metodi standard:

  • tramite un gestore di pacchetti di sistema come apt, apk, yum, brew, ecc.;
  • tramite un gestore di pacchetti per linguaggi di programmazione come pip, npm, composer, gem, cargo, ecc.;
  • compilando nel container attraverso make, mvn, ecc.

Di seguito vi mostriamo alcuni esempi di componenti software comunemente usati nei container Docker:

Area d’applicazione Componenti software
Linguaggi di programmazione PHP, Python, Ruby, Java, JavaScript
Strumenti per lo sviluppo node/npm, React, Laravel
Sistemi di database MySQL, Postgres, MongoDB, Redis
Server web Apache, nginx, lighttpd
Cache e proxy Varnish, Squid
Sistemi di gestione del contenuto WordPress, Magento, Ruby on Rails

Variabili d’ambiente e configurazioni di runtime

Seguendo la metodologia dell’app a dodici fattori, la configurazione del container Docker è memorizzata in variabili d’ambiente, chiamate “Env-Vars”. Qui, il termine “configurazione” viene inteso come tutti i valori che cambiano tra i diversi ambienti, quali lo sviluppo o il sistema di produzione. Questo spesso include nomi host e credenziali di database.

I valori delle variabili d’ambiente influenzano il comportamento del container. Si usano due metodi principali per rendere disponibili le variabili d’ambiente all’interno di un container:

1. Definizione nel Dockerfile

La dichiarazione ENV dichiara una variabile d’ambiente nel Dockerfile. È possibile assegnare anche un valore predefinito opzionale che entra in vigore se la variabile d’ambiente è vuota all’avvio del container.

2. Trasferimento all’avvio del container

Per accedere a una variabile d’ambiente nel container che non è stata dichiarata nel Dockerfile, è possibile trasferire la variabile all’avvio del container, il che funziona per singole variabili tramite parametri della riga di comando. Inoltre, si può trasferire un “file env”, che definisce diverse variabili d’ambiente insieme ai loro valori.

Di seguito vi mostriamo come trasferire una variabile d’ambiente all’avvio del container:

docker run --env <env-var> <image-id></image-id></env-var>

È utile trasferire un file env per molte variabili d’ambiente:

docker run --env-file /path/to/.env <image-id></image-id>
N.B.

Il comando “docker inspect” può essere utilizzato per visualizzare le variabili d’ambiente presenti nel container insieme ai loro valori. Pertanto, è necessario fare attenzione quando si utilizzano dei dati riservati nelle variabili d’ambiente.

Quando si avvia un container da un’immagine, possono essere trasferiti dei parametri di configurazione. Questi includono la quantità di risorse di sistema allocate che altrimenti è illimitata. Inoltre, i parametri di avvio sono utilizzati per definire porte e volumi per il container. Ne discuteremo più a fondo nel prossimo paragrafo. I parametri di avvio possono sovrascrivere qualsiasi valore predefinito nel Dockerfile. Di seguito vi mostriamo alcuni esempi.

Per allocare un core della CPU e 10 megabyte di RAM nel container Docker all’avvio bisognerà inserire il seguente codice:

docker run --cpus="1" --memory="10m" <image-id></image-id>

Per aprire le porte definite nel Dockerfile all’avvio del container si dovrà procedere come segue:

docker run -P <image-id></image-id>

Per mappare la porta TCP 80 dell’host Docker sulla porta 80 del container Docker bisognerà inserire quanto segue:

docker run -p 80:80/tcp <image-id></image-id>

Porte e volumi

Un container Docker contiene un’applicazione isolata dal mondo esterno. Per dimostrare la sua utilità, deve essere possibile l’interazione con l’ambiente. Pertanto, esistono dei modi per scambiare dati tra host e container, così come tra più container. Le interfacce standardizzate permettono ai container di essere usati in diversi ambienti.

La comunicazione dall’esterno con i processi in esecuzione nel container avviene su porte di rete esposte. Questa utilizza i protocolli standard TCP e UDP. Ad esempio, immaginiamo un container Docker che contiene un server web. Questo scansiona la porta TCP 8080. Il Dockerfile dell’immagine Docker contiene anche la riga 'EXPOSE 8080/tcp'. Bisognerà avviare il container con 'docker run -P' e accedere al server web su 'http://localhost:8080'.

Le porte sono usate per comunicare con i servizi in esecuzione nel container. Tuttavia, in molti casi, per scambiare dati può essere utile usare un file condiviso tra il container e il sistema host. Questo è il motivo per cui Docker riconosce diversi tipi di volumi:

  • Volume denominato - raccomandato
  • Volumi anonimi - vengono persi quando il container viene rimosso
  • Supporti bind- storici e non raccomandati; performanti
  • Supporti Tmpfs - situati nella RAM; solo su Linux

Le differenze tra i tipi di volume sono sottili e la scelta del tipo più adatto dipende molto dall’uso che se ne fa. Una descrizione dettagliata di tali differenze, tuttavia, andrebbe oltre lo scopo di questo articolo.

Processi e registri

Un container Docker di solito incapsula un’applicazione o un servizio. Il software eseguito all’interno del container forma un insieme di processi in esecuzione. I processi in un container Docker sono isolati dai processi in altri container o dal sistema host. I processi possono essere avviati, fermati ed elencati all’interno di un container Docker controllato tramite la riga di comando o tramite l’API Docker.

I processi in esecuzione emettono continuamente delle informazioni di stato. Seguendo la metodologia dell’app a dodici fattori, vengono utilizzati dei flussi di dati standard STDOUT e STDERR per l’output. L’output su questi due flussi di dati può essere letto con il comando “docker logs”. Anche Il cosiddetto “logging driver” può essere usato in questo caso. Il driver di registrazione predefinito scriverà i log in formato JSON.

Come e dove si usano i container Docker?

Al giorno d’oggi Docker è usato in tutte le parti del ciclo vitale del software. Questo include sviluppo, test e funzionamento. I container in esecuzione su un host Docker sono controllati tramite l’API Docker. Il client Docker accetta i comandi dalla riga di comando mentre degli speciali strumenti di orchestrazione vengono usati per controllare i cluster di container Docker.

Lo schema di base per distribuire i container Docker ha orientativamente la seguente struttura:

  1. L’host Docker scarica l’immagine Docker dal registro.
  2. Il container Docker viene creato e avviato dall’immagine.
  3. L’applicazione nel container viene eseguita finché il container non viene fermato o rimosso.

Di seguito mostriamo due esempi di distribuzione di container Docker.

Distribuire i container Docker nell’ambiente di sviluppo locale

L’uso dei container Docker è particolarmente popolare nello sviluppo di software. Di solito, un software viene sviluppato da un team di specialisti. Per questo scopo viene utilizzato un insieme di strumenti di sviluppo noto come una catena di strumenti. Ogni strumento è in una versione specifica e l’intera catena funziona solo se le versioni sono compatibili tra loro. Inoltre, gli strumenti devono essere configurati correttamente.

Per assicurarsi che l’ambiente di sviluppo sia coerente, gli sviluppatori usano Docker. Un’immagine Docker viene creata una volta sola e contiene l’intera toolchain correttamente configurata. Ogni sviluppatore del team estrae l’immagine Docker dalla propria macchina locale e avvia un container da essa. Lo sviluppo avviene quindi all’interno del container e se vi è un cambiamento nella toolchain l’immagine viene aggiornata centralmente.

Distribuzione di container Docker in cluster orchestrati

I data center dei fornitori di hosting e dei fornitori di Platform as a Service (PaaS) usano cluster di container Docker. Ogni servizio (load balancer, server web, server di database, ecc.) viene eseguito nel proprio container Docker. Allo stesso tempo, un singolo container può gestire solo un certo carico. Un software di orchestrazione monitora i container, il loro carico e il loro stato. L’orchestratore avvia ulteriori container quando il carico aumenta. Questo approccio permette ai servizi di scalare rapidamente in risposta al cambiamento delle condizioni.

Vantaggi e svantaggi della virtualizzazione basata su container di Docker

I vantaggi della virtualizzazione con Docker possono essere visti in particolare se messi a confronto con l’uso di macchine virtuali (VM). I container Docker sono molto più leggeri delle VM, possono essere avviati più velocemente e consumano meno risorse. Le immagini alla base dei container Docker sono anche più piccole di diversi ordini di grandezza. Infatti, mentre le immagini delle macchine virtuali sono di solito abbastanza grandi, da centinaia di MB a qualche GB, le immagini Docker partono da pochi MB.

Tuttavia, la virtualizzazione basata su container di Docker presenta anche alcuni svantaggi. Poiché un container non contiene il proprio sistema operativo, l’isolamento dei processi in esecuzione non è del tutto perfetta. L’uso di molti container comporta un alto grado di complessità. Inoltre, Docker è un sistema evoluto e al giorno d’oggi la piattaforma Docker ha troppe funzioni. Gli sviluppatori stanno quindi lavorando duramente per dividere i singoli componenti.

Hai trovato questo articolo utile?
Per offrirti una migliore esperienza di navigazione online questo sito web usa dei cookie, propri e di terze parti. Continuando a navigare sul sito acconsenti all’utilizzo dei cookie. Scopri di più sull’uso dei cookie e sulla possibilità di modificarne le impostazioni o negare il consenso.
Page top