Docker è una piattaforma che consente l’esecuzione di containers, contenenti applicazioni. L’analisi architetturale di docker consente di comprendere il funzionamento della piattaforma diffusa tra i programmatori.
Poichè la piattaforma consente di monitore in maniera piuttosto dettagliata (utilizzando eventualmente componenti esterni, come Kubernates) è consigliato effettuare il deploy di ogni componente dell’applicazione finale come un singolo containers. Questo approccio è tipico dello sviluppo di microservices.
Containers e immagini
Il containers è l’elemento base di docker: si tratta in pratica di un’unità software pacchettizzata e contentente tutto il necessario per eseguire l’applicazione (configurazione, codice buildato, librerie e dipendenze).

I container sono poco onerosi in termini di risorse di sistema, condividendo sostanzialmente il kernel della macchina virtuale su cui vengono eseguite. Consentendo la separazione tra architettura e applicazione è molto utilizzando nello sviluppo devops, nella distribuzione e aggiornamento di applicazioni. L’isolamento offerto dal container, inoltre, garantisce che l’esecuzione dell’applicazione non subisca interferenze dal tipo di architettura utilizzata, cloud o on-premise.
Al concetto di container è strettamente legato quello di immagine. Un’immagine è una template che consente di creare uno o più containers. Le tre caratteristiche di un’immagine sono:
- è immutabile
- non viene eseguita direttamente: per poter essere eseguita deve avvenire prima il build della stessa
- non ha uno stato associato
Un’immagine è un modello completo di quello che sarà contenuto all’interno del container: è un file (o eventulamente una serie di file) con le direttive che dovranno essere eseguite per la creazione del containers.
Facendo un paragone con la programmazione ad oggetti, l’immagine è la definizione della classe, mentre l’oggetto (istanza) della classe è il container.
Un’immagine è un elemento statico, mentre un container è elemento dinamico (eseguito a runtime). Quando viene richiesta l’esecuzione di un container, il container engine alloca a runtime le risorse richieste e avvia il container stesso a partire dal suo filesystem. Al termine dell’allocazione viene eseguito il comando specificato all’interno del docker file, all’interno della direttiva ENTRYPOINT .
Docker Engine
Docker Engine è il core dell’intera archiettura di docker ed è basato su un’architettura di tipo client / server composta da componenti:
- server: lo strato sul quale vengono eseguiti i singoli container. Inoltre, ha il compito di gestire lo strato rete, lo strato risorse condivise e le immagini. Espone una serie di API Rest.
- client: un’interfaccia a linea di comando (CLI) che consente all’utente di inviare comandi alla componente server. L’interfacciamento avviene tramite API Rest.
- registry: un repositository dal quale è possibile scaricare e “pushare” le immagini da utilizzare. La natura del repository può essere pubblica o privata: il repository pubblico contiene immagini che possono essere scaricate e messe a disposizione da altri utenti. Il repository privato è invece accessibile ai membri dell’organizzazione che l’ha creata. Il registry pubblico di Docker è Docker Hub.

Alcuni comandi che possono essere impartiti tramite linea di comando:
- docker build: consente di effettuare il build di un container a partire da un docker file
- docker create: consente di creare un nuovo contenitore a partire da un’immagine
- docker start: consente di mandare in esecuzione un container
- docker run: consente di creare e mandare in esecuzione un container
Comandi utili
L’interfaccia CLI di docker consente di eseguire operazioni per effettuare il monitoraggio e la gestione dei containers. Tra questi, possiamo trovare:
- docker ps [-a] : elenco dei containers in esecuzione
- docker port container-name : ispezionare le porta usate da un contenitore
- docker inspect container-name : per ispezionare un contenitore
- docker logs container-name : per visualizzare i log di un container
- docker stop container-name : per arrestare un container in esecuzione
- docker rm container-name : per rimuovere un container
- docker rmi image-name : per rimuovere un’immagine
Volumi e condivisioni dei dati
Al termine dell’esecuzione di un container (o in caso di distruzione), i dati in esso contenuto vengono persi. Per ovviare a questo problema è stato introdotto il concetto di volume.
Un volume (spesso definito anche data volume) è una porzione di file system che può essere condiviso tra più containers. Essendo una porzione di file system consente di gestire la persistenza dei dati , indipendentemente dal ciclo di vita dei containers stessi.
E’ possibile allocare un volume in due modi:
- montare una cartella dell’host come volume all’interno di un container, utilizzando l’opzione -v. In questo caso i dati risiedono all’interno del volume e non nel container. Tipicamente questo tipo di operazione viene effettuato per la ridirezione dei log (e la loro persistenza)
- creare una struttura di volumi condivisi tra i contenitori: questa tipologia di condivisione viene utilizzata per la realizzazione di microservices
Best Practices
Alcune raccomandazioni per quanto riguarda l’utilizzo di containers e delle immagini:
- realizzare un container per ogni singolo processo, in modo da consentire il riuso (di immagini e containers ) e di ottenere maggiore scalabilità
- realizzare containers il più possibile “volatili”, in modo da poter essere sostituiti con altri con funzionalità simili
- containers minimali, che utilizzano immagini il più ridotte possibile, evitando l’installazione di package non necessari