Docker: terminologia base

Spread the love

Partire con Docker non è difficile ma mi sono trovato subito a fare confusione tra questi tre termini: image, container, volume. Provo a spiegarmeli con l’aiuto di questi articoli veramente chiari di Sofija Simic che trovate linkati alla fine del post e che rimastico quà e là un po’ a modo mio.

Differenza tra image e container

Cos’è un’immagine Docker?

Un’immagine Docker (image) è un file immutabile (non modificabile) che contiene il codice sorgente, le librerie, le dipendenze, gli strumenti e altri file necessari per l’esecuzione di un’applicazione.

A causa della loro qualità di sola lettura, queste immagini sono talvolta denominate istantanee (snapshots). Rappresentano un’applicazione e il suo ambiente virtuale in un momento specifico. Questa coerenza è una delle grandi caratteristiche di Docker. Consente agli sviluppatori di testare e sperimentare software in condizioni stabili e uniformi.

Poiché le immagini sono, in un certo senso, solo modelli (templates), non è possibile avviarle o eseguirle. Quello che puoi fare è usare quel modello come base per costruire un contenitore.

Un contenitore è, in definitiva, solo un’immagine in esecuzione.

Una volta creato un contenitore, viene aggiunto un livello scrivibile sopra l’immagine immutabile, il che significa che ora puoi modificarlo.

L’immagine di base dalla quale crei un contenitore esiste separatamente e non può essere modificata. Quando si esegue un ambiente containerizzato, si crea essenzialmente una copia di lettura e scrittura di quel filesystem (immagine docker) all’interno del container. Ciò aggiunge un livello contenitore che consente le modifiche dell’intera copia dell’immagine.

Docker: container e uno stack di images
Docker: container e uno stack di images

Puoi creare un numero illimitato di immagini Docker da un’unica immagine di base. Ogni volta che modifichi lo stato iniziale di un’immagine e salvi lo stato esistente, crei un nuovo modello con un livello aggiuntivo sopra di esso, in una struttura a pila (stack).

Le immagini Docker possono, quindi, essere costituite da una serie di livelli, ciascuno diverso ma anche originato dal precedente. I livelli immagine rappresentano file di sola lettura a cui viene aggiunto un livello contenitore una volta utilizzati per avviare un ambiente virtuale.

Cos’è un container Docker?

Un container Docker è un ambiente di runtime virtualizzato in cui gli utenti possono isolare le applicazioni dal sistema sottostante. Questi contenitori sono unità compatte e portatili in cui è possibile avviare un’applicazione in modo rapido e semplice.

Una caratteristica preziosa è la standardizzazione dell’ambiente di calcolo in esecuzione all’interno del container. Non solo garantisce che la tua applicazione funzioni in circostanze identiche, ma semplifica anche la condivisione con altri collaboratori.

Poiché i container sono autonomi, essi forniscono un forte isolamento, assicurando che non interrompano altri container in esecuzione, nonché il server che li supporta. Docker afferma che queste unità “forniscono le più potenti capacità di isolamento del settore”. Pertanto, non dovrai preoccuparti di proteggere la tua macchina durante lo sviluppo di un’applicazione.

A differenza delle macchine virtuali (VM) in cui la virtualizzazione avviene a livello di hardware, i container vengono virtualizzati a livello di app. Possono utilizzare una macchina, condividere il suo kernel e virtualizzare il sistema operativo per eseguire processi isolati. Ciò rende i contenitori estremamente leggeri, consentendo di trattenere risorse preziose.

Differenza tra macchina virtuale (VM) e Container Docker
Differenza tra macchina virtuale (VM) e Container Docker

Contenitori contro Immagini

Quando si parla della differenza tra immagini e contenitori, un errore che capita di fare è quello di metterli in contrasto come entità antagoniste. Entrambi gli elementi sono invece strettamente correlati e fanno parte di un sistema definito dalla piattaforma Docker.

Se hai letto le due sezioni precedenti che definiscono le immagini e i contenitori Docker, potresti già avere una certa comprensione di come i due stabiliscono una relazione.

Le immagini possono esistere senza contenitori, mentre un contenitore deve eseguire un’immagine per esistere.

Pertanto, i contenitori dipendono dalle immagini e le utilizzano per creare un ambiente di runtime ed eseguire un’applicazione.

I due concetti esistono come componenti essenziali (o meglio come fasi) nel processo di esecuzione di un container Docker. Avere un contenitore in esecuzione è la “fase” finale di quel processo, a indicare che dipende dai passaggi e dai componenti precedenti. Ecco perché le immagini Docker essenzialmente governano e modellano i contenitori.

Dal Dockerfile all’image al container

Tutto inizia con uno script di istruzioni che definiscono come creare un’immagine Docker specifica. Questo script è chiamato Dockerfile. Eseguendo un Dockerfile, vengono eseguiti singolarmente i comandi elencati e viene creata un’immagine Docker.

Il comando per creare un’immagine da un Dockerfile è docker build.

L’immagine viene quindi utilizzata come modello (o base), che uno sviluppatore può copiare e utilizzarla per eseguire un’applicazione. L’applicazione necessita di un ambiente isolato in cui eseguire: un container.

Questo ambiente non è solo uno “spazio” virtuale. Si basa interamente sull’immagine che lo ha creato. Il codice sorgente, i file, le dipendenze e le librerie binarie, che si trovano tutti nell’immagine Docker, costituiscono un contenitore.

Per creare un contenitore da un’immagine, usa il comando docker create.

Infine, dopo aver avviato un contenitore da un’immagine esistente, ne avvii il servizio ed esegui l’applicazione.

Riutilizzo di un contenitore come immagine

Se apporti modifiche all’immagine iniziale e desideri conservarla per lavori futuri, puoi salvare l’immagine modificata facendo uno screenshot dello stato corrente del contenitore. In questo modo, alleghi un livello contenitore sopra l’immagine, costruendo infine una nuova immagine immutabile. Di conseguenza, ti ritroverai con due immagini Docker derivate dallo stesso filesystem.

Docker volumes: creazione e utilizzo

I volumi Docker sono strumenti ampiamente utilizzati e utili per garantire la persistenza dei dati mentre si lavora nei container. Sono un’alternativa migliore rispetto alla compilazione di livelli scrivibili aggiuntivi, che aumentano le dimensioni dell’immagine Docker.

In pratica si potrebbero scrivere i contenuti dentro ai container ma così facendo se distruggiamo il container perdiamo anche i dati.

Cosa sono i volumi Docker?

I volumi Docker sono file systems montati su container Docker per preservare i dati generati dal container in esecuzione.

È come se montassimo un hard disk USB nel nostro filesystem per utilizzare i dati anche a computer spento.

I volumi vengono archiviati nell’host, indipendentemente dal ciclo di vita del contenitore. Ciò consente agli utenti di eseguire facilmente il backup dei dati e condividere file system tra contenitori.

Primi passi con i volumi

Esistono diversi modi per montare un volume Docker durante l’avvio di un container. Si possono utilizzare in alternativa i flag -v e --mount, che vengono aggiunti al comando docker run.

Questo articolo mostra esempi di entrambi i flag in uso.

Funzioni di manutenzione dei volumi

Creare un volume Docker

Per creare un volume Docker utilizzare il comando:

$ docker volume create [volume_name]

In conseguenza a questo comando, Docker crea una directory per il volume sull’host nel percorso /var/lib/docker/volume/. È ora possibile montare questo volume su un container, garantendo la persistenza dei dati e la condivisione dei dati tra più container.

Ad esempio, per creare un volume con il nome data, eseguire il comando:

$ docker volume create data

Elenco dei volumi

Per verificare di aver creato correttamente un volume Docker, chiedi a Docker di elencare tutti i volumi disponibili con:

$ docker volume list

Nelle prove fatte finora ho creato un po’ di volumi e questo è il risultato

# docker volume ls
DRIVER    VOLUME NAME
local     0effd02df709acd840c431ad7ffa8c24f19107b0fc534cd86b47b2d7a2d38ded
local     83eac56a552efee4167050921b771395da0100f94df95b72bee7fdbfb95c9ff0
local     35409dbb5911bf3ad9454375a7d4c855f5fe46f7800acc3a0e8b204417b274f0
local     b6c20a389cc440e77208aa62c48792f3c3d381253ba200fbb7779048eb729d72

L’output visualizza un elenco di volumi, specificando la loro posizione (DRIVER) e il loro nome VOLUME NAME.

Si può vedere la stessa situazione dal file system dell’host, a parttire dalla posizione in cui Docker crea i volumi:

$ ls -l /var/lib/docker/volumes
totale 48
drwx-----x  6 root root  4096 ago  9 10:17 ./
drwx--x--- 13 root root  4096 ago  9 10:17 ../
drwx-----x  3 root root  4096 giu 29 17:25 0effd02df709acd840c431ad7ffa8c24f19107b0fc534cd86b47b2d7a2d38ded/
drwx-----x  3 root root  4096 giu 29 12:25 35409dbb5911bf3ad9454375a7d4c855f5fe46f7800acc3a0e8b204417b274f0/
drwx-----x  3 root root  4096 giu 29 12:12 83eac56a552efee4167050921b771395da0100f94df95b72bee7fdbfb95c9ff0/
drwx-----x  3 root root  4096 giu 29 17:08 b6c20a389cc440e77208aa62c48792f3c3d381253ba200fbb7779048eb729d72/
brw-------  1 root root  8, 1 ago  9 10:17 backingFsBlockDev
-rw-------  1 root root 32768 ago  9 10:17 metadata.db

Ispezionare i volumi

Per visualizzare ulteriori informazioni su un volume Docker, utilizzare il comando inspect:

# docker volume inspect b6c20a389cc440e77208aa62c48792f3c3d381253ba200fbb7779048eb729d72
[
    {
        "CreatedAt": "2022-06-29T17:13:42+02:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/b6c20a389cc440e77208aa62c48792f3c3d381253ba200fbb7779048eb729d72/_data",
        "Name": "b6c20a389cc440e77208aa62c48792f3c3d381253ba200fbb7779048eb729d72",
        "Options": null,
        "Scope": "local"
    }
]

Il comando elenca i dettagli di un volume, inclusa la sua posizione nel filesystem host (Mountpoint). Tutto ciò che è memorizzato all’interno del volume di dati può essere trovato anche nella directory elencata sotto il percorso del punto di montaggio.

Montare un volume in un container

Come quando si monta un disco USB collegandolo ad una porta del computer, per montare un volume di dati in un contenitore, aggiungi il flag --mount al comando docker run. Docker aggiunge il volume al contenitore specificato, dove archivia i dati prodotti all’interno dell’ambiente virtuale.

Per eseguire un container e montarvi un volume di dati, segui la sintassi di base:

$ docker run --mount source=[volume_name],destination=[path_in_container] [docker_image]

Basta sostituire [path_in_container] con il percorso in cui desideri posizionare il volume di dati nel contenitore (ad esempio /app/data). Tutto ciò che è memorizzato in quella directory viene automaticamente salvato anche sul volume di dati sull’host.

Ad esempio, per avviare un contenitore Ubuntu e montarvi il volume di dati, eseguire:

$ docker run -it --name=example1 --mount source=data,destination=/app/data myimage

Il comando indica a Docker di eseguire (run) un contenitore in modalità interattiva (-it, in conseguneza a questa opzione si aprirà una shell sul contenitore) dall’immagine myimage, con il nome example1, mentre monta i dati del volume nella directory /app/data all’interno del contenitore.

Quindi, controlla per verificare che il volume sia stato montato correttamente elencando il contenuto del contenitore con il comando ls dalla console del contenitore.

Riferimenti

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.