Introduzione

Un'immagine Docker è il progetto dei contenitori Docker che contiene l'applicazione e tutto il necessario per eseguire l'applicazione. Un contenitore è un'istanza di runtime di un'immagine.

In questo tutorial, spiegheremo cos'è Dockerfile, come crearne uno e come costruire/creare un'immagine Docker con Dockerfile.

Cos'è Dockerfile

Un file Docker è un file di testo che contiene tutti i comandi che un utente potrebbe eseguire sulla riga di comando per creare un'immagine. Include tutte le istruzioni necessarie a Docker per creare l'immagine.

Le immagini Docker sono costituite da una serie di livelli di filesystem che rappresentano le istruzioni nel file Docker dell'immagine che costituisce un'applicazione software eseguibile.

Il file Docker ha la forma seguente:

# Comment
INSTRUCTION arguments

INSTRUCTION non fa distinzione tra maiuscole e minuscole, ma la convenzione prevede l'uso di MAIUSCOLO per i suoi nomi.

Di seguito è riportato un elenco con una breve descrizione di alcune delle istruzioni Dockerfile più utilizzate:

  • ARG : Questa istruzione consente di definire variabili che possono essere passate in fase di compilazione. Puoi anche impostare un valore predefinito.
  • FROM - L'immagine di base per la creazione di una nuova immagine. Questa istruzione deve essere la prima istruzione senza commenti nel file Docker. L'unica eccezione a questa regola è quando si desidera utilizzare una variabile FROM nell'argomento. In questo caso, FROM può essere preceduto da una o più istruzioni ARG.
  • LABEL: Utilizzata per aggiungere metadati a un'immagine, ad esempio descrizione, versione, autore ..etc. Puoi specificare più di uno LABEL e ogni istruzione LABEL è una coppia chiave-valore (key-value).
  • RUN - I comandi specificati in questa istruzione verranno eseguiti durante il processo di compilazione. Ogni istruzione RUN crea un nuovo livello sopra l'immagine corrente.
  • ADD: utilizzato per copiare file e directory dalla sorgente specificata alla destinazione specificata sull'immagine Docker. La fonte può essere file o directory locali o un URL. Se l'origine è un archivio tar locale, viene automaticamente decompresso nell'immagine Docker.
  • COPY- Simile a ADD ma l'origine può essere solo un file o una directory locale.
  • ENV : Questa istruzione consente di definire una variabile di ambiente.
  • CMD : Utilizzato per specificare un comando che verrà eseguito quando si esegue un contenitore. È possibile utilizzare solo un'istruzione CMD nel Dockerfile.
  • ENTRYPOINT - Simile a CMD, questa istruzione definisce quale comando verrà eseguito quando si esegue un contenitore.
  • WORKDIR - Questa direttiva imposta la directory di lavoro corrente per le istruzioni RUN, CMD, ENTRYPOINT, COPY, e ADD.
  • USER - Impostare il nome utente o UID per l'uso durante l'esecuzione di eventuali le istruzioni seguenti RUN, CMD, ENTRYPOINT, COPY, e ADD.
  • VOLUME : Consente di montare una directory del computer host sul contenitore.
  • ESPOSIZIONE : utilizzato per specificare la porta su cui il contenitore è in ascolto in fase di esecuzione.

Per, escludere file e directory dall'aggiunta all'immagine, creare un file .dockerignore nella directory di contesto (context). La sintassi di .dockerignore è simile a quella del file Git .gitignore.

Per un riferimento completo e una spiegazione dettagliata delle istruzioni Dockerfile, consultare la pagina di riferimento ufficiale Dockerfile.

Creare un file Docker

Lo scenario più comune durante la creazione di immagini Docker è estrarre un'immagine esistente da un registro (in genere dall'hub Docker) e specificare le modifiche che si desidera apportare sull'immagine di base. L'immagine di base più comunemente usata durante la creazione di immagini Docker è Alpine perché è piccola e ottimizzata per essere eseguita nella RAM.

Docker Hub è un servizio di registro basato su cloud che, tra le altre funzionalità, viene utilizzato per conservare le immagini Docker in un repository pubblico o privato.

In questo esempio, creeremo un'immagine Docker per il server Redis. Useremo l'ultimo Ubuntu 18.04 come immagine di base.

Innanzitutto, crea una directory che conterrà il file Docker e tutti i file necessari:

mkdir ~/redis_docker

Cambiare directory e creare il seguente Dockerfile:

cd ~/redis_docker
nano Dockerfile
FROM ubuntu:18.04

RUN apt-get update && \
    apt-get install -y redis-server && \
    apt-get clean

EXPOSE 6379

CMD ["redis-server", "--protected-mode no"]

Spieghiamo il significato di ciascuna delle linee nel Dockerfile:

  • In linea 1 stiamo definendo l'immagine di base.
  • Le istruzioni RUN che iniziano in linea 3 e aggiorneranno l'indice apt, installeranno il pacchetto "redis-server" e puliranno la cache apt. I comandi usati nelle istruzioni sono gli stessi dei comandi che useresti per installare redis sul server Ubuntu.
  • L'istruzione EXPOSE definisce la porta su cui il server redis è in ascolto.
  • Nell'ultima riga, stiamo usando le istruzioni CMD per impostare il comando predefinito che verrà eseguito quando il contenitore viene eseguito.

Salvare e chiudere il file premendo CTRL+X, seguito da Y per salvare le modifiche e quindi ENTER se stai utilizzando nano.

Costruire (build) l'immagine

Il prossimo passo è costruire l'immagine. Per fare ciò, eseguire il comando seguente dalla directory in cui si trova Dockerfile:

docker build -t noviello/redis .

L'opzione -t specifica il nome dell'immagine e, facoltativamente, un nome utente e un tag nel formato "nome utente/imagename: tag".

L'output del processo di compilazione sarà simile al seguente:

Sending build context to Docker daemon  3.584kB
Step 1/4 : FROM ubuntu:18.04
 ---> 7698f282e524
Step 2/4 : RUN apt-get update &&     apt-get install -y gosu redis-server &&     apt-get clean
 ---> Running in e80d4dd69263
...
Removing intermediate container e80d4dd69263
 ---> e19fb7653fca
Step 3/4 : EXPOSE 6379
 ---> Running in 8b2a45f457cc
Removing intermediate container 8b2a45f457cc
 ---> 13b92565c201
Step 4/4 : CMD ["redis-server", "--protected-mode no"]
 ---> Running in a67ec50c7048
Removing intermediate container a67ec50c7048
 ---> d8acc14d9b6b
Successfully built d8acc14d9b6b
Successfully tagged noviello/redis:latest

Una volta completato il processo di compilazione, la nuova immagine verrà elencata nell'elenco delle immagini:

docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
noviello/redis      latest              d8acc14d9b6b        4 minutes ago       100MB
ubuntu              18.04               7698f282e524        5 days ago          69.9MB

Se si desidera inviare l'immagine all'hub Docker, consultare Pushing a Docker container image to Docker Hub.

Eseguire un contenitore

Ora che l'immagine è stata creata, esegui un contenitore eseguendo:

docker run -d -p 6379:6379 --name redis noviello/redis

L'opzione -d indica a Docker di eseguire il contenitore in modalità separata, l'opzione -p 6379:6379 pubblicherà l'immagine sulla porta 6379 del computer host e l'opzione --name redis specifica il nome del contenitore. L'ultimo argomento noviello/redis è il nome dell'immagine che viene utilizzato per eseguire il contenitore.

All'avvio del contenitore, utilizzare il comando seguente per elencare tutti i contenitori in esecuzione:

docker container ls
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                    NAMES
6b7d424cd915        noviello/redis:v0.0.1   "redis-server '--pro…"   5 minutes ago       Up 5 minutes        0.0.0.0:6379->6379/tcp   redis

Per verificare che tutto funzioni come dovrebbe utilizzare redis-cli per connettersi al contenitore docker:

redis-cli ping

Il server redis dovrebbe rispondere con PONG.

Conclusione

Questo tutorial ha trattato solo le basi dell'utilizzo dei Dockerfile per creare immagini. Per ulteriori informazioni su come scrivere Dockerfile e le best practice consigliate, consultare Best practice per la scrittura di Dockerfile.