Skip to content

Come risolvere alcune insidie nell’uso dei container

Scopri Docker e il mondo dei containers e impara a risolvere le insidie ​​che puoi incontrare nell’utilizzo di queste tecnologie

Questo articolo ripercorre tutti i passaggi che hanno portato alla containerizzazione, partendo dai server, passando per le macchine virtuali per arrivare ai container. Verrà analizzata l’architettura Docker e in modo particolare come risolvere alcune insidie ​​che si possono incontrare nell’utilizzo di questa tecnologia.

Questo articolo è il risultato della mia esperienza nella creazione e distribuzione di applicazioni dotnet e c# tramite macchine virtuali e nell’ultimo anno con Docker.

La prima volta che ho creato un’applicazione ho dovuto distribuirla tramite macchina virtuale e creare l’intero ambiente, partendo da zero, è stato particolarmente difficile e laborioso, senza considerare il fatto che fosse la mia prima esperienza.

Non molto tempo dopo, un giorno al lavoro, qualcuno mi disse che esisteva una sorta di “strumento magico” che ti permette di distribuire le applicazioni in pochi passaggi, semplicemente digitando alcuni comandi. Ovviamente pensavo che scherzasse e che mi prendesse in giro, ma invece era tutto vero, così da quel giorno tutto è cambiato!

Dall’età della pietra alla virtualizzazione

In passato, se si voleva pubblicare online un’applicazione era necessario configurare letteralmente un computer e un servizio web dedicato, chiamato server. Ma con il passare del tempo, questo sistema rendeva molto difficile la gestione del software, e così sono arrivate le macchine virtuali (VM).

Una macchina virtuale non è altro che la virtualizzazione di un server fisico; ciò significa che le risorse hardware possono essere suddivise in più parti al fine di eseguire quelli che sembrano essere molti computer separati su hardware ma che in realtà è un solo computer. Come si può immaginare, tutto ciò può diventare molto costoso in termini di risorse hardware, hosting e tempo di installazione e configurazione della macchina, per non parlare del pesante utilizzo del sistema operativo.

Ad esempio, immaginiamo di installare WordPress in locale, per fare questo si dovrebbero eseguire numerosi passaggi prima di arrivare in fondo. E proprio per evitare questa lunga procedura è meglio utilizzare i container.

Dalla virtualizzazione alla containerizzazione

I Container possono essere considerati come una sorta di evoluzione delle macchine virtuali, che introduce importanti innovazioni nella tecnica tradizionale.

Il concetto è leggermente diverso da quello delle macchine virtuali, infatti i container condividono lo stesso kernel del sistema operativo e isolano i processi applicativi dal resto dell’infrastruttura. Questo sistema ottimizza l’utilizzo delle risorse e riduce la necessità di sistemi operativi ridondanti.

1. Struttura delle macchine virtuali e dei containers

Come si può vedere dall’immagine, il componente principale della virtualizzazione, l’hypervisor, un software che gestisce tutte le macchine virtuali in esecuzione sulla macchina host, è stato sostituito da un nuovo componente, il container engine, che ha il compito di far girare i containers.

Cos’è Docker?

Docker è una piattaforma open source utilizzata per lo sviluppo, l’esecuzione e la distribuzione delle applicazioni con l’utilizzo dei container. Docker utilizza un’architettura di tipo Client-Server e questi sono i componenti principali:

  1. docker: il client che invia comandi e richieste al server;
  2. dockerd: il server che gestisce i container e le immagini;
  3. registry (Docker Hub): un registry pubblico in cui si possono trovare tutte le immagini pubbliche e su cui è possibile eseguire anche le proprie immagini private.
2. Come funziona Docker

Il client invia le richieste, digitate dall’utente, al server. I comandi docker utilizzano le API di Docker e il docker deamon resta in ascolto nell’attesa di nuove richieste e può trovare le immagini richieste su Docker Hub.

Vantaggi nell’utilizzo dei containers

Ci sono tanti vantaggi nell’utilizzo dei containers, ecco qui i più importanti:

  • leggeri: i container occupano soltanto qualche megabyte e impiegano qualche secondo per avviarsi;
  • deploy semplificato: l’unità di deploy è un’immagine autoconsistente e versionata pronta per essere eseguita;
  • scalabilità: un container che gira su un’istanza docker può essere facilmente replicato su un’altra con le stesse funzionalità e la stessa consistenza;
  • isolamento: le dipendenze e le impostazioni all’interno dei container non influiscono sulle configurazioni del computer oppure su qualsiasi altro container in esecuzione;
  • sicurezza: le applicazioni in esecuzione sui container sono completamente isolate l’una dalle altre, ciò significa che nessun container può vedere i processi che sono in esecuzione dentro ad un altro né tantomeno interferire con il loro funzionamento.
Quando dovresti usare Docker

Come ho spiegato sopra, l’utilizzo di Docker porta molti vantaggi nello sviluppo e nella gestione di un’applicazione, ma ovviamente questo strumento non è la soluzione a tutto. Infatti ci sono molti scenari in cui è ancora preferibile continuare ad utilizzare le macchine virtuali. È opportuno pertanto definire in quali situazioni è meglio utilizzare Docker.

Prima di tutto se si ha a che fare con un’architettura di microservizi la containerizzazione è la scelta migliore. I microservizi sono un tipo di architettura che struttura l’applicazione come una raccolta di servizi. I sistemi software nascono generalmente come applicazioni monolitiche, in cui l’interfaccia utente e il codice di accesso ai dati sono combinati in un unico programma, ma con la crescita dell’applicazione, un monolite può diventare difficile da mantenere e distribuire. Al contrario i microservizi scompongono i sistemi in funzioni più semplici, che possono essere implementate in modo indipendente. Questo è il motivo per cui i container sono il miglior host per i microservizi, perché sono autonomi, facilmente implementabili ed efficienti.

Se si ha un team di sviluppatori che lavorano con configurazioni diverse, Docker dà la possibilità di avere ambienti di sviluppo locali simili a quelli di produzione.

Ed infine quando si ha la necessità di pubblicare l’applicazione su più fasi di sviluppo (dev, test, produzione).

MA, c’è un enorme “ma”, perché Docker può presentare anche degli svantaggi, come vedremo qui di seguito.

Potenziali insidie nell’utilizzo di Docker

Nonostante Docker abbia così tanti vantaggi, è possibile però incontrare alcune insidie come:

  • gestione dei dati: se si vuole preservare i dati si deve fare in modo di non scriverli all’interno dei containers, perché se si rimuove o si riavvia il container si perdono inesorabilmente tutti i dati. Esistono due soluzioni a questo problema: volumi o bind mount. Il primo richiede di memorizzare i dati in una parte specifica del file system dell’host, che si chiama docker volumes directory, ed è gestito da docker, mentre l’altro dà la possibilità di memorizzarli in una directory qualunque del file system della macchina host;
  • scrivere correttamente un Dockerfile oppure un Docker Compose file: nessuno ci dice cosa dobbiamo scrivere all’interno di un Dockerfile o di un Docker Compose file, quindi si è costretti a fare qualche ricerca sul web e sperare di trovare quello che ci serve;
  • buona conoscenza della Shell di Linux: è necessario avere una buona conoscenza di Linux in generale, ma in modo particolare della Shell, perché per poter interagire con i containers si deve utilizzare il prompt dei comandi e per far questo è essenziale sapere come usarlo;
  • nessuna interfaccia utente: non c’è un’interfaccia grafica vera e propria con cui interagire, come ho scritto sopra l’unico modo per interagire è tramite console, la quale non risulta per niente intuitiva;
  • debug: il debug è molto complicato e lento, risulta essere una perdita di tempo durante lo sviluppo.

Alcune di queste insidie ​​possono essere risolte nel contesto in cui ci troviamo e in cui si sta sviluppando (come per esempio il discorso del debug), mentre altre, per esempio come scrivere correttamente un Dockerfile, sono problemi ricorrenti.

Overview

l segreto sta nel capire come costruire immagini e come orchestrale, ma prima di tutto dobbiamo definire alcuni termini importanti.

Dockerfile

Un dockerfile è un file di testo che definisce un’immagine docker tramite una sintassi semplice e concisa. Mentre un’immagine docker è un modello di sola lettura contenente istruzioni per la creazione di un docker container, il quale è un’istanza di un’immagine docker. Ogni istruzione del dockerfile crea un livello sull’immagine e quando si modifica il dockerfile e si ricostruisce l’immagine, vengono ricostruiti soltanto i livelli che sono stati modificati.

3.Tutti gli step necessari per l’ esecuzione di un container

In breve: devi scrivere un dockerfile per costruire un’immagine che esegue dei containers.
Di seguito un esempio di Dockerfile.

FROM node:8
WORKDIR /usr/src/app
COPY package*.json
RUN npm install
COPY . .
EXPOSE 8080
CMD ["npm", "start"]

Queste sono alcune delle principali istruzioni che si possono trovare in un Dockerfile:

  1. FROM: è sicuramente l’istruzione più importante, nonché l’unica che non può mai mancare, perché inizializza una nuova build e imposta l’immagine di base da cui partire.
  2. WORKDIR: crea una directory di lavoro dell’applicazione per altre istruzioni come RUN, COPY e ADD, che la seguono nel dockerfile.
  3. COPY: installa tutte le dipendenze dell’applicazione.
  4. RUN: questo comando genera un nuovo livello, che porta con sé le modifiche derivate dal comando stesso, infatti è consigliato inserire più comandi correlati all’interno di una singola istruzione RUN. In questo caso abbiamo npm come comando e install come parametro, il che vuol dire installare un’applicazione e tutti i pacchetti necessari per il corretto funzionamento.
  5. EXPOSE: consente a Docker di sapere su quali porte il container resterà in ascolto durante il runtime. È importante avere chiaro che questo comando non apre automaticamente le porte specificate, ma fa sapere a Docker, durante la creazione dell’immagine, che deve eseguire un forwarding delle porte.
  6. CMD: ha effetto sul container quindi non modifica l’immagine né aggiunge nuovi livelli. Questa istruzione imposta il comando da eseguire durante l’esecuzione dell’immagine, inoltre si può aggiungere una sola istruzione cmd all’interno del Dockerfile.
    E adesso? Cosa devo fare con queste immagini? Bene, ora, se si ha la necessità di eseguire applicazioni Docker che richiedono sia back-end che front-end, allora dobbiamo usare qualcosa per definire ed eseguire applicazioni multi-container ovvero Docker Compose.
Docker Compose

Docker Compose è uno strumento di orchestrazione per applicazioni complesse con funzionalità minime.

Tuttavia, se si vuole utilizzare Docker Compose si deve

  1. definire l’app environment con un dockerfile;
  2. scrivere un docker-compose.yml file;
  3. eseguire un comando speciale (docker-compose up).

Ora, se prendiamo come esempio il problema di WordPress che ho presentato all’inizio, possiamo facilmente risolverlo con Docker Compose.

Qui abbiamo il file.

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress

All’inizio del file ci sono tutti i servizi di cui abbiamo bisogno per far funzionare WordPress, poi c’è la sezione di gestione dei dati (da notare la soluzione dei volumi che ho spiegato prima) e la sezione di WordPress con tutte le sue variabili d’ambiente.
Ed infine non resta che eseguire il comando docker-compose up.

Conclusioni

Sicuramente Docker è uno strumento molto potente e all’avanguardia, ma come tutte le tecnologie, si deve saperlo usare nel modo giusto e prima ancora si deve sapere come funziona, perché altrimenti si rischia di non poter sfruttare al meglio tutte le potenzialità di questo strumento.
In sintesi:

  1. la virtualizzazione non è abbastanza;
  2. ora i containers sono lo standard;
  3. DockerFile e Docker Compose sono ok ma per scenari semplici;
  4. per tutto il resto c’è il CLOUD (Kubernetes, Azure container instance, OpenWhisk, ecc..).