Non perdere le offerte a tempo limitato!

Tutorial Docker: guida completa all’esecuzione dei container

Tutorial Docker: guida completa all’esecuzione dei container

Docker è una piattaforma open source progettata per semplificare lo sviluppo, la distribuzione e l’esecuzione delle applicazioni. Semplifica la distribuzione del software grazie alla containerizzazione, una tecnologia che racchiude la tua applicazione e tutte le sue dipendenze in unità isolate ed eseguibili chiamate container. In questo modo, il software funziona in modo coerente, indipendentemente dall’ambiente in cui lo esegui.

Alla base, Docker ruota attorno ad alcuni concetti chiave: Docker Engine, Docker Hub, le immagini Docker, i container, i Dockerfile e Docker Compose. Comprendere questi componenti ti permette di creare, distribuire e gestire applicazioni containerizzate in modo efficace.

Puoi usare Docker tramite la riga di comando, ma la piattaforma offre anche una versione desktop con interfaccia grafica. Il processo di configurazione è diverso: puoi installare la versione desktop come una normale applicazione .dmg o .exe, mentre la CLI richiede l’installazione tramite un gestore di pacchetti come APT o Homebrew.

Quando utilizzi l’ecosistema Docker, possono verificarsi errori a diversi livelli, che riguardano l’immagine Docker, il Dockerfile o il container stesso. Poiché questi problemi possono compromettere l’intero sistema di containerizzazione, è importante conoscere gli errori più comuni, le loro cause e le possibili soluzioni. Li analizzeremo più avanti, dopo aver esaminato i concetti fondamentali di Docker.

Che cos’è la containerizzazione?

La containerizzazione è una tecnologia di virtualizzazione a livello di sistema operativo che consente di eseguire le applicazioni in spazi utente isolati chiamati container.

Un container include un’applicazione insieme a tutti i componenti necessari — codice, librerie di sistema, dipendenze e file di configurazione — creando un ambiente isolato e coerente.

A differenza delle macchine virtuali (VM), i container sono più leggeri perché condividono il kernel del sistema operativo dell’host. Questa indipendenza dall’infrastruttura sottostante permette alle applicazioni di funzionare in modo uniforme in ambienti diversi.

I vantaggi della containerizzazione includono:

  • Portabilità. I container funzionano in modo coerente in qualsiasi ambiente, dalla tua macchina locale a un server remoto fornito da provider come Hostinger. In questo modo eviti i problemi di compatibilità che possono verificarsi quando sposti un’applicazione tra sistemi diversi durante la distribuzione o il lavoro in team.
  • Efficienza. Le VM richiedono un sistema operativo guest completo e un hypervisor, mentre i container no. Per questo rappresentano una soluzione di virtualizzazione più leggera ed efficiente.
  • Isolamento. Ogni container esegue processi isolati, con il proprio software, la propria configurazione, il proprio stack di rete e le proprie variabili d’ambiente. Questo aumenta la sicurezza e riduce il rischio di conflitti tra applicazioni.

Perché usare Docker?

Dovresti usare Docker perché offre un modo affidabile, efficiente e standardizzato per creare, condividere ed eseguire applicazioni. Ti aiuta a risolvere diversi problemi concreti legati allo sviluppo e alla distribuzione del software:

  • Il problema del “ma sul mio computer funziona”. Docker garantisce che un’applicazione venga eseguita esattamente allo stesso modo per ogni sviluppatore e in ogni fase della produzione, eliminando i bug legati alle differenze di ambiente.
  • Sviluppo e distribuzione più rapidi. Docker semplifica la creazione di ambienti riproducibili. Puoi integrare funzionalità come mappe o gateway di pagamento senza doverle sviluppare da zero, risparmiando tempo.
  • Scalabilità e portabilità. Con strumenti come Docker Compose puoi definire in un unico file uno stack applicativo multi-container e condividerlo facilmente, mantenendo coerenza tra i team e scalando i servizi in base alle necessità.
  • Efficienza delle risorse. Poiché i container sono leggeri e condividono il kernel del sistema operativo dell’host, richiedono meno risorse rispetto alle macchine virtuali tradizionali.

Quali sono i concetti fondamentali di Docker?

Docker organizza la containerizzazione in un insieme di componenti fondamentali e interdipendenti. Questi elementi lavorano insieme come una piattaforma che gestisce l’intero ciclo di vita di un’applicazione containerizzata, dalla creazione del blueprint iniziale fino all’esecuzione dell’applicazione finale multi-servizio

Docker Engine

Docker Engine è la tecnologia open source alla base della creazione e della gestione di applicazioni containerizzate. Utilizza un’architettura client-server per gestire tutti gli oggetti Docker, come immagini Docker, container e reti.

Le tre parti principali di Docker Engine sono:

  1. Il server. Un processo daemon in esecuzione continua (dockerd) che gestisce tutte le attività principali, come la creazione, l’avvio e l’eliminazione dei container.
  2. API. Interfacce che permettono ai programmi, inclusa la Docker CLI, di comunicare con il daemon e inviargli istruzioni.
  3. Il client CLI. Lo strumento a riga di comando di Docker, che rappresenta il modo principale con cui interagisci con la piattaforma.

Per capire meglio questo concetto, puoi immaginare Docker Engine come lo chef, la cucina e il cameriere di un ristorante.

  • Il server (dockerd) è lo chef che prepara il cibo, ovvero esegue il container nel contesto di Docker.
  • Le API sono il menu e le comande che indicano allo chef cosa preparare.
  • La Docker CLI è il cameriere che prende i tuoi ordini sotto forma di comandi e li trasmette alla cucina.

Per verificare se Docker Engine è in esecuzione e correttamente connesso al client, esegui un comando per controllare se risponde alla tua richiesta. Ad esempio:

docker ps

Questo comando chiede al daemon di Docker di elencare tutti i container attualmente in esecuzione. Se Docker Engine funziona correttamente, vedrai un elenco dei container attivi.

Docker Hub

Docker Hub è il registro pubblico predefinito di Docker, ovvero un servizio di archiviazione e distribuzione delle immagini Docker. Ospita immagini ufficiali di software popolari come nginx, node e python e ti permette di creare repository privati per le tue immagini personalizzate.

Quando crei un container, devi utilizzare diversi pacchetti software basati sulle immagini. Docker Hub semplifica questo processo perché ti consente di scaricare immagini Docker da un repository centralizzato.

Docker Hub utilizza i tag per etichettare e identificare le immagini. I tag indicano una versione specifica del pacchetto software, ad esempio latest. In questo modo mantieni coerenza e compatibilità dei container tra ambienti diversi.

Puoi immaginare Docker Hub come una biblioteca di ricette condivisa dalla community. Contiene ricette già pronte per piatti comuni che puoi scaricare e usare per preparare un pasto. Puoi anche caricare le tue ricette, sia per condividerle sia per conservarle come backup privati.

Puoi interagire con Docker Hub usando la Docker CLI. Per esempio, per scaricare un’immagine dal registro esegui:

docker pull <name>:<tag>

Ad esempio, per scaricare l’ultima immagine ufficiale di Ubuntu:

docker pull ubuntu:latest

Immagini Docker

Un’immagine Docker è un modello in sola lettura che contiene tutte le istruzioni e i file necessari per creare un container Docker. Include il codice dell’applicazione, i file di configurazione, le librerie di sistema e i file del sistema operativo di base.

Le immagini Docker vengono create a partire da un Dockerfile, in cui ogni istruzione genera un livello distinto e immutabile che definisce cosa l’immagine deve contenere o fare.

In altre parole, un’immagine è il progetto di una macchina. Contiene un insieme di istruzioni che descrivono esattamente cosa deve includere il prodotto finale, ma non può essere modificata una volta creata. Quando segui questo blueprint, ottieni un container Docker.

Per elencare le immagini scaricate in locale, usa:

docker images

Il comando seguente crea un’immagine nella directory corrente assegnandole un nome e un tag specifici. Se l’immagine di base non è già presente in locale, Docker la scaricherà automaticamente da Docker Hub:

docker build -t your-image-name:latest .

Una buona pratica quando lavori con le immagini Docker è scegliere un’immagine di base minimale, così riduci le dimensioni complessive e limiti la superficie di attacco potenzialmente introdotta da pacchetti o componenti non necessari.

Container Docker

Un container è un’istanza eseguibile di un’immagine Docker. È lo spazio isolato in cui viene eseguita la tua applicazione, insieme alla configurazione, alle dipendenze e ai pacchetti software necessari.

Quando crei un container Docker, viene aggiunto un livello scrivibile sopra i livelli in sola lettura dell’immagine Docker, così puoi modificare i file nel filesystem locale del container.

I container sono progettati per essere effimeri o stateless, il che significa che puoi arrestarli, eliminarli, ricostruirli e sostituirli con una configurazione minima. Un singolo container si gestisce con la Docker CLI, mentre più container si amministrano usando Docker Compose o uno strumento di orchestrazione come Kubernetes.

Riprendendo la stessa analogia, un container è la macchina effettivamente in esecuzione, costruita a partire dal progetto, cioè dall’immagine. Quando crei un container Docker, assembli e avvii quella macchina per eseguire i processi definiti nell’immagine Docker.

Per creare un container Docker ed eseguire un comando al suo interno, usa il comando run:

docker run -it ubuntu /bin/bash

Questo comando esegue l’immagine Ubuntu, avvia un container interattivo ed esegue la shell /bin/bash.

Dockerfile

Un Dockerfile è un file di testo semplice che contiene una sequenza di istruzioni passo per passo per creare un’immagine Docker. Definisce tutto, dal sistema operativo di base alle variabili d’ambiente fino al codice dell’applicazione.

Ecco alcune delle istruzioni più comuni in un Dockerfile e il loro scopo:

  • FROM. Specifica l’immagine di base per un nuovo stage di build.
  • RUN. Esegue comandi durante il processo di build dell’immagine.
  • COPY o ADD. Copia i file dal contesto di build all’interno dell’immagine.
  • CMD o ENTRYPOINT. Definisce il comando eseguito all’avvio del container.
  • ENV. Imposta variabili d’ambiente disponibili durante la build e in fase di esecuzione.
  • WORKDIR. Imposta la directory di lavoro per le istruzioni RUN, CMD, ENTRYPOINT, COPY e ADD successive.

Alcune istruzioni del Dockerfile creano un layer, ovvero un passaggio nel processo di build dell’immagine. Le istruzioni che impostano configurazioni o metadati, come WORKDIR, invece non creano un nuovo layer.

Ecco un esempio di Dockerfile:

FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]

Docker Compose

Docker Compose è uno strumento che semplifica la definizione e la gestione di applicazioni multi-container utilizzando un unico file di configurazione, in genere chiamato docker-compose.yml.

All’interno del file di configurazione puoi definire tutti i container, le reti e i volumi necessari per creare uno stack applicativo complesso. Successivamente, puoi avviare e gestire tutti i container, chiamati servizi nel contesto di Docker Compose, con un unico comando.

Senza Docker Compose dovresti configurare manualmente ogni container e gestirli singolarmente tramite la Docker CLI. Se la tua applicazione include più servizi interconnessi, questo processo diventa complesso e richiede molto tempo.

Se un container è un singolo elettrodomestico, Docker Compose è lo schema elettrico di un’intera cucina. Definisce come forno, frigorifero e tostapane sono collegati e avviati insieme tramite un unico interruttore per svolgere le rispettive funzioni.

Ecco un esempio di file Docker Compose:

services:
  web:
    build: ./web  # Crea l’immagine dal Dockerfile nella directory ./web
    ports:
      - "8000:8000"  # Mappa la porta 8000 dell’host alla porta 8000 del container
    depends_on:
      - db     # Attende l’avvio del servizio db
      - redis  # Attende l’avvio del servizio redis

  db:
    image: postgres:15  # Usa l’immagine ufficiale PostgreSQL 15
    environment:
      POSTGRES_USER: myuser       # Imposta il nome utente del database
      POSTGRES_PASSWORD: mypassword  # Imposta la password del database
      POSTGRES_DB: mydb           # Imposta il nome iniziale del database
    volumes:
      - db-data:/var/lib/postgresql/data  # Mantiene persistenti i dati del database

  redis:
    image: redis:alpine  # Usa un’immagine Redis leggera per la cache

volumes:
  db-data:  # Definisce un volume con nome per archiviare i dati del database

Per creare e avviare in background tutti i servizi definiti nel file docker-compose.yml, esegui il comando con il flag -d (detached):

docker compose up -d

Metodi per installare Docker

Il processo di installazione di Docker varia in base alla versione che scegli. Se utilizzi Docker Desktop, puoi scaricare il pacchetto di installazione dalla pagina ufficiale e installarlo come qualsiasi altra applicazione.

In alternativa, puoi installare la Docker CLI eseguendo i comandi tramite il gestore di pacchetti del tuo sistema operativo, come APT su Ubuntu o Homebrew su macOS. Consulta la documentazione ufficiale per conoscere i comandi specifici per configurare Docker sul tuo sistema.

Tieni presente che la Docker CLI non include alcune funzionalità, come Docker Compose, quindi devi installarle separatamente. Se utilizzi la soluzione di hosting Docker di Hostinger, non è necessario configurarlo a parte, perché la funzionalità integrata Docker Manager include il supporto a Compose.

Comprendere i comandi Docker di base

Usa la Docker CLI per interagire con Docker Engine e gestire i container. Ecco alcuni dei comandi Docker più importanti per le attività più comuni:

  • docker ps -a. Elenca tutti i container, inclusi quelli arrestati.
  • docker pull <name>:<tag>. Scarica un’immagine dal registro sul tuo computer locale.
  • docker rmi <image>. Elimina un’immagine locale.
  • docker stop <container>. Arresta in modo corretto un container in esecuzione.
  • docker rm <container>. Elimina un container.

Per un elenco completo dei comandi più utilizzati per immagini, container, volumi e altre risorse, consulta la nostra cheat sheet su Docker.

Come gestire i volumi Docker

I volumi sono il meccanismo principale per garantire la persistenza dei dati in Docker, assicurando che rimangano disponibili anche dopo la rimozione di un container.

Questo aspetto è fondamentale perché, durante il ciclo di vita dei container, potresti doverli rimuovere per aggiornamenti o manutenzione. Se il container esegue applicazioni come un database, dove l’integrità dei dati è essenziale, configurare correttamente i volumi è indispensabile.

Docker offre tre tipi principali di archiviazione:

  • Volumi. Conservano i dati persistenti dei container nell’area di archiviazione di Docker, che di solito si trova in /var/lib/docker/volumes/ sul sistema host.
  • Bind mount. Mappano un file o una directory dalla macchina host direttamente nel container.
  • Mount tmpfs. Memorizzano i dati nella memoria dell’host; i dati vengono persi quando il container si arresta.

Ecco i passaggi per creare e gestire un volume per i dati persistenti:

  1. Crea un volume con nome usando il comando seguente. Ad esempio, questo crea un volume chiamato my-database-data:
docker volume create my-database-data
  1. Avvia il container del database usando il flag -v per collegare il volume con nome alla directory interna dei dati del container:
docker run -d \
  --name my-database \
  -e MYSQL_ROOT_PASSWORD=securepassword \
  -v my-database-data:/var/lib/mysql \
  mysql:latest
  1. Ispeziona i dettagli e la posizione del volume sull’host eseguendo:
docker volume inspect my-database-data
  1. Per rimuovere i volumi inutilizzati che non sono associati ad alcun container e liberare spazio su disco, usa:
docker volume prune -a

In alternativa ai comandi, puoi dichiarare e montare un volume direttamente nel file YAML di Docker Compose. In questo modo puoi tenere traccia più facilmente dei volumi utilizzati da ciascun container, soprattutto quando gestisci più servizi.

Ad esempio, la configurazione YAML seguente riproduce i passaggi precedenti per creare un volume e montarlo nel container:

services:

  my-database:

    image: mysql:latest

    container_name: my-database

    environment:
      MYSQL_ROOT_PASSWORD: securepassword

    volumes:
      - my-database-data:/var/lib/mysql

volumes:
  my-database-data:

Crea una rete Docker

Le reti Docker mantengono l’isolamento tra i container e consentono la comunicazione con altri container e sistemi esterni. Per impostazione predefinita, i container sono collegati a una rete bridge. Per configurare la comunicazione in un’applicazione multi-servizio, crea una rete bridge definita dall’utente.

Docker collega automaticamente un container alla rete bridge predefinita, che gli permette di comunicare con l’host. Tuttavia, questa rete non è adatta a configurazioni multi-container, perché offre funzionalità limitate per la comunicazione tra servizi.

Per le applicazioni multi-servizio, la best practice è creare una rete bridge definita dall’utente. In questo modo i container possono comunicare tra loro usando i nomi dei servizi. Questo semplifica la scoperta dei servizi, migliora il controllo sulle interazioni tra container e riduce le interferenze tra servizi.

Puoi collegare un container a una rete bridge definita dall’utente aggiungendo la direttiva networks alla configurazione del servizio nel file YAML di Docker Compose. Ecco un esempio:

services:

  my-database:

    image: mysql:latest

    container_name: my-database

    environment:
      MYSQL_ROOT_PASSWORD: securepassword

    volumes:
      - my-database-data:/var/lib/mysql

    networks:
      - my-app-network # Crea una rete

In alternativa, puoi creare una rete bridge definita dall’utente con il comando seguente, dove my-app-network è il nome della rete:

docker network create my-app-network

Successivamente, avvia il container usando la Docker CLI con il flag –name per assegnare un nome al servizio e –network per specificare la rete a cui collegarlo:

docker run -d \
  --name my-database \
  --network my-app-network \
  -e MYSQL_ROOT_PASSWORD=securepassword \
  -v my-database-data:/var/lib/mysql \
  mysql:latest

Se vuoi avviare e collegare un altro container alla stessa rete, ripeti il comando aggiornando le informazioni del servizio. Nell’esempio seguente aggiungiamo il flag -p per pubblicare la porta interna 80 del container sulla porta 8080 dell’host, così da renderla accessibile dall’esterno:

docker run -d \
  --name my-webapp \
  --network my-app-network \
  -p 8080:80 \
  my-web-app-image:latest

Risoluzione dei problemi comuni di Docker

Quando lavori con Docker, i problemi più comuni riguardano il sistema a livelli, incluse immagini Docker, container, volumi e reti. Di seguito analizziamo le criticità più frequenti e le relative soluzioni.

Il container si arresta immediatamente

Un container può arrestarsi subito dopo l’avvio perché il processo principale, definito da CMD o ENTRYPOINT nel Dockerfile, termina l’esecuzione o va in crash. Una causa comune è il tentativo di eseguire un servizio in background senza usare la modalità detached.

Ecco alcune soluzioni possibili:

  • Controlla i log. Usa docker logs <container_name> per visualizzare lo stdout e lo stderr dell’applicazione e individuare la causa dell’errore.
  • Verifica le direttive del Dockerfile. Assicurati che il container esegua un processo a lunga durata controllando che nel Dockerfile sia presente CMD o ENTRYPOINT. Ad esempio, un server web deve rimanere attivo per gestire le richieste.
  • Esegui in modalità detached. Se l’applicazione è un servizio a esecuzione prolungata e vuoi eseguirlo in background, usa il flag -d o –detach quando lanci docker run o docker compose run.

Problemi di caching dei layer dell’immagine

Se le modifiche al Dockerfile, come l’aggiornamento della versione di un pacchetto, non hanno effetto, potresti avere un problema con la cache dei layer di Docker. Questo meccanismo riutilizza i layer creati in precedenza per velocizzare la build dell’immagine, invece di ricostruirli da zero.

Sebbene migliori le prestazioni, può causare problemi quando modifichi i layer iniziali del Dockerfile, perché le istruzioni successive potrebbero non essere aggiornate correttamente.

La soluzione più semplice è forzare una ricostruzione completa ignorando la cache. Puoi farlo aggiungendo l’opzione –no-cache durante la build, ad esempio:

docker build --no-cache -t my-app:latest .

Quando installi pacchetti in un Dockerfile, includi esplicitamente un comando che impedisca al gestore dei pacchetti di riutilizzare layer obsoleti con elenchi di pacchetti non aggiornati. Nelle distribuzioni basate su Debian, puoi farlo combinando apt-get update e apt-get install -y –no-install-recommends nello stesso comando RUN, ad esempio:

RUN apt-get update && apt-get install -y --no-install-recommends

Errore di autenticazione del registro

Se ricevi un errore come “denied: requested access to the resource is denied” quando esegui il push di un’immagine su un registry, ad esempio Docker Hub, significa che la Docker CLI non è autenticata con il server del registry.

Per risolvere il problema, accedi al registro e autentica il tuo account seguendo questi passaggi:

  1. Accedi al registro con il comando seguente, sostituendo my-registry.example.com con l’indirizzo effettivo del registry. Se vuoi pubblicare un’immagine su Docker Hub, puoi omettere l’indirizzo:
docker login my-registry.example.com
  1. Inserisci il nome utente e la password quando richiesto.
  2. Assegna il tag corretto all’immagine, includendo l’host del registry, il repository e il tag, prima di eseguire il push:
docker tag my-local-image:latest my-registry.example.com/my-repo/my-local-image:latest
  1. Esegui il push dell’immagine sul registry con il comando:
docker push my-registry.example.com/my-repo/my-local-image:latest

Quali sono i prossimi passi per padroneggiare Docker?

Per padroneggiare Docker e usarlo in scenari reali di produzione, devi andare oltre l’uso di un singolo container e dei comandi di base. I passaggi successivi includono l’apprendimento di tecniche avanzate per distribuire e gestire applicazioni complesse ad alta disponibilità.

Oltre a Docker Compose, è importante imparare strumenti di orchestrazione avanzati come Docker Swarm o Kubernetes per gestire e scalare più container su un cluster di macchine.

Approfondisci anche i driver di rete, come l’Overlay Network Driver utilizzato nella modalità Swarm di Docker per collegare più host all’interno di un cluster. Collegare più macchine usando la rete predefinita di Docker richiede una configurazione manuale e complessa, mentre le reti overlay semplificano e automatizzano la comunicazione tra host in modo scalabile e affidabile.

Infine, esplora i principali casi d’uso di Docker per comprendere meglio come utilizzare questo strumento di containerizzazione nelle diverse fasi di sviluppo e distribuzione delle applicazioni.

Tutti i contenuti dei tutorial presenti su questo sito web sono soggetti ai rigorosi standard editoriali e ai valori di Hostinger.

Author
L'autore

Faradilla Ayunindya

Faradilla, conosciuta anche come Ninda, è Content Marketing Specialist in Hostinger, con oltre 5 anni di esperienza nel settore e un background di 10 anni come linguista. Si dedica a rendere la tecnologia più accessibile, adattando guide complesse in tutorial chiari e facili da seguire. Nel tempo libero, quando non è impegnata a seguire le ultime tendenze del mondo tech e del digital marketing, ama approfondire temi legati alle scienze della vita o guardare video divertenti di animali. Puoi connetterti con lei su LinkedIn.

Cosa dicono i nostri clienti

Lascia un commento

Please fill the required fields.Please accept the privacy checkbox.Please fill the required fields and accept the privacy checkbox.

Thank you! Your comment has been successfully submitted. It will be approved within the next 24 hours.