In questo articolo parliamo di cosa sono i container ma soprattutto di come possano essere utili nella vita quotidiana di ogni informatico – non solo programmatori – in ogni fase del proprio lavoro, dallo sviluppo alla formazione alla sperimentazione.

Quando parliamo di container intendiamo delle unità software che racchiudono in sé tutto il necessario affinché un’applicazione possa funzionare. Possiamo considerare un container un habitat completo ma essenziale per far funzionare un’applicazione. A differenza delle macchine virtuali essi non astraggono l’hardware bensì il sistema operativo. Pertanto, qualora volessimo creare un’applicazione da distribuire potremmo produrre un container adeguato a essa, completo di ogni dipendenza e di qualsiasi risorsa necessaria (immagini, dataset, configurazioni e molto altro).

Se per esempio volessimo preparare un ambiente di esecuzione per una nostra applicazione sfruttando una macchina fisica o virtuale dovremmo per prima cosa munirla di un sistema operativo, installato e ben configurato, dotarla poi di tutto il necessario al funzionamento dell’applicazione, includendo dipendenze librerie e risorse. Oltre al tempo e alle energie necessarie, dovremmo considerare che una macchina virtuale avrebbe necessità di disporre di risorse in quanto a spazio di archiviazione (il suo hard disk virtuale), una quota di memoria RAM e capacità di elaborazione misurata in core del processore. Tutto ciò potrebbe risultare oneroso se paragonato alle dimensioni tipiche di tante applicazioni.

Vantaggi di Docker

Spesso si ricorre ad approcci simili, ma in molti altri casi è più efficiente utilizzare i container grazie ai quali si può creare un ambiente minimale contenente solo ed esclusivamente le dipendenze dell’applicazione ed eventuali configurazioni: tutto il resto di cui il container ha bisogno per lavorare lo mette a disposizione il sistema operativo sottostante.

Il formato più conosciuto e più utilizzato in assoluto per i container è quello creato da Docker tanto che quest’ultimo è diventato uno strumento assolutamente centrale nel panorama informatico e tecnologico attuale.

Quello che si ottiene utilizzando i container è innanzitutto un’altissima portabilità, essedo questi elementi compatti, completi e organici, perfetti per essere trasferiti dall’ambiente in cui stiamo sviluppando e  testando software a quello di produzione (ormai molto spesso in Cloud) con la garanzia di avere il medesimo funzionamento.

Inoltre, le dimensioni dei container assolutamente ridotte ne permettono un’ottima scalabilità e sappiamo essere questa il meccanismo centrale con cui le applicazioni in Cloud possono reagire all’aumento di carichi di lavoro improvvisi con tutti i vantaggi in fatto di progettazione e gestione dei costi.

Passiamo ora a capire come Docker può essere utile allo sviluppatore in ogni singola giornata, indipendentemente dal fatto che questi lo voglia utilizzare per poter eseguire le proprie applicazioni.

Docker: indispensabile per tutti

Docker può essere installato in qualsiasi ambiente seguendo le istruzioni che vengono messe a disposizione sul sito ufficiale del progetto sia in ambiente Linux (con cui Docker ha una grande familiarità) sia su Windows sia su sistemi Mac.

Inoltre se si vuole prendere confidenza con questa tecnologia la si può utilizzare in una serie di altri contesti dove lo troviamo già installato, perfettamente configurato e gratuito.

Solo per fare alcuni esempi possiamo pensare alla Cloud Shell della Google Cloud Platform,  un ambiente Linux gratuito disponibile a chiunque abbia a disposizione delle credenziali Gmail (la posta elettronica di Google estremamente diffusa). In tale ambiente possiamo trovare Docker già pronto e disponibile alla nostra sperimentazione.

Per fare un altro esempio (ma si potrebbero citare tante altre fonti) esiste il Playground di Docker, un altro ambiente gratuito al quale si può accedere mediante registrazione e dove si ha la possibilità di lanciare un’istanza con ambiente per container già pronto.

Utilizzando Docker, sin dai primi istanti, si apprende che si hanno a disposizione delle immagini pronte, offerte da Docker Hub, il registry ufficiale del mondo Docker ovvero il servizio che mette a disposizione di chiunque la possibilità di condividere le proprie immagini e scaricare quelle altrui.

Docker: come si usa

Passiamo ora a vedere alcuni casi in cui Docker può rivelarsi assolutamente fondamentale nello studio, nella sperimentazione e nel lavoro di ogni giorno.

Per esempio, potremmo desiderare di sperimentare una distribuzione Linux senza doverla installare nel nostro computer né predisporre appositamente una macchina virtuale.

Supponiamo di essere interessati al sistema operativo Ubuntu. In un ambiente in cui Docker è già presente possiamo semplicemente chiedergli di avviare questa distribuzione recuperando automaticamente l’immagine da Docker Hub e  il tutto con un solo comando:

$ docker run -it ubuntu:22.04

Tutto viene gestito mediante lo strumento Docker. Il suo comando run indica che vogliamo mandare in esecuzione l’immagine che segue, nel nostro caso una versione 22.04 di Ubuntu. L’opzione -it indica che non vogliamo che il container sia eseguito in maniera isolata ma vogliamo che attivi opportuni canali di dialogo interattivo con la nostra console. Il risultato sarà che avremo, nel giro di pochi secondi, a disposizione un nuovo prompt che non sarà più quello da cui abbiamo avviato il comando Docker bensì il terminale in cui potremo utilizzare la distribuzione Ubuntu che abbiamo richiesto.

$ > docker run -it ubuntu:22.04

root@1f412b18c2e9:/# cat /etc/lsb-release

DISTRIB_ID=Ubuntu

DISTRIB_RELEASE=22.04

DISTRIB_CODENAME=jammy

DISTRIB_DESCRIPTION="Ubuntu 22.04.1 LTS"

Nel momento in cui daremo il comando exit, verrà chiusa la console e usciremo dall’esecuzione del container Ubuntu. Questo è un esempio di come si possa sperimentare velocemente un sistema, anche piuttosto complesso, come una distribuzione Linux direttamente avendo solo a disposizione Docker.

Container Python in Docker

Altro esempio riguarda la sperimentazione dei linguaggi di programmazione. Immaginiamo di voler utilizzare la console di Python e di non averla a disposizione per provare alcune funzionalità.

Identicamente a come abbiamo fatto poco fa, ci basterà richiedere l’avvio di un container Python:

$ > docker run -it python

Python 3.11.2 (main, Feb 11 2023, 02:24:27) [GCC 10.2.1 20210110] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> a=10

>>> b=8

>>> print(f'Risultato della somma {a}+{b}={a+b}')

Risultato della somma 10+8=18

In questo caso abbiamo sperimentato l’uso di variabili e della funzione print all’interno della versione 3.11 di Python. Questo utilizzo può essere molto comodo per verificare l’esistenza o l’efficacia di determinate funzionalità su versioni diverse di uno stesso linguaggio. Per esempio, per chi conosce il linguaggio Python quella f che abbiamo inserito all’interno della funzione print introduce una cosiddetta f-string, funzionalità molto comoda ma esistente solo dalla versione 3.6. Se volessimo verificarne la disponibilità su una versione precedente di Python, supponiamo la 3.4, potremmo semplicemente avviare un’immagine relativa a questa versione dello stesso linguaggio. Una sperimentazione di questo tipo risulterebbe così assolutamente comoda:

$ > docker run -it python:3.4

Python 3.4.10 (default, Mar 20 2019, 00:50:15)

[GCC 6.3.0 20170516] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> a=10

>>> b=8

>>> print(f'Risultato della somma {a}+{b}={a+b}')

  File "<stdin>", line 1

    print(f'Risultato della somma {a}+{b}={a+b}')

                                               ^

SyntaxError: invalid syntax

La sperimentazione condotta (che effettivamente ha prodotto errore nella versione Python precedente alla 3.6) è stata portata a termine in maniera pratica, immediata, senza richiedere l’installazione reale su una nostra macchina né di Python 3.6 né di Python 3.4.

Docker su localhost

A questi esempi possiamo aggiungere un altro caso molto utile che consiste nell’avvio di un servizio su un nostro sistema collegandolo a localhost ovvero l’indirizzo di rete su cui una macchina risponde internamente.  Se volessimo sperimentare l’uso di un database senza doverlo installare potremmo avviare la relativa immagine collegando le porte del container a quelle relative su localhost.

$ docker run \

   --name=mydb -p3306:3306 -d --rm \

   -v myvolume:/var/lib/mysql \

   -e MYSQL_ROOT_PASSWORD=mypassword -d mysql:8

In questo esempio, avviamo un server MySQL in cui impostiamo una password di root, un volume per la memorizzazione persistente dei dati di nome myvolume ma soprattutto con l’espressione -p3306:3306  andiamo a indicare che la porta di default del server per database MySQL dovrà essere collegata alla stessa porta di localhost.

Fatto ciò, con il container attivo, potremo scrivere un programma in un qualsiasi linguaggio all’interno della nostra macchina in grado di dialogare con il server database in ascolto su localhost ma eseguito nel container. Questo va a risolvere un problema tipico di molti sviluppatori e informatici in genere che per avere a disposizione un servizio di qualche tipo sono costretti a installarlo nel proprio ambiente di lavoro con tutte le complicazioni del caso.

Conclusioni

Oltre a riepilogare le basi dei container e di Docker abbiamo visto alcuni aspetti importanti ed esempi che indicano come questa tecnologia così fondamentale nello sviluppo moderno di applicazioni e di architetture in Cloud possa essere utilissima nel lavoro di ogni giorno di qualsiasi informatico che si si tratti di studio,  sperimentazione o produzione. Qualunque servizio ci servirà potremo agilmente metterlo a nostra disposizione avendo semplicemente installato Docker e lanciando l’immagine opportuna.