Esempio molto semplice con annessa spiegazione di un file docker-compose.yml

Cos'è docker-compose? Come scrivo il docker-compose.yml?

13-07-2020

Eccomi di nuovo qui a parlare di Docker! Questa volta voglio spiegarti in dettaglio cos’è e cosa puoi fare con docker-compose e come scrivere un file di configurazione molto semplice.

Ti ho spiegato, nel precedente articolo, come installare Docker sulla tua macchina o su un server Linux. Subito dopo aver installato Docker siamo passati ad installare l’utility docker-compose. Su Linux va installato a parte, su sistemi Windows e MacOS invece è “gratis”, l’exe o il dmg che installa Docker ci installa anche docker-compose.

Ma cos’è docker-compose?

Nell’articolo precedente, per installare Portainer ho lanciato il comando docker seguito da alcuni paramentri, questo mi ha permesso di configurare e lanciare in esecuzione un singolo container. Immagina di volerti servire di Docker per lo sviluppo di un tuo progetto e che, trattandosi si un progetto web, hai bisogno di nginx e MySQL. Bene, solo 2 container. Dovrai lanciare un comando docker run ... per ognuno dei container che ti occorre, e per spegnerli? Altri 2 comandi docker stop .... E per riavviarli? Già… Hai capito dove voglio andare a parare.

L’utility docker-compose ci permette, tramite un unico file di configurazione, di organizzare e documentare tutti i componenti di un’applicazione in vari container (con immagini che possiamo prelevare dal DockerHub o crearci noi stessi tramite la scrittura di un Dockerfile, ne parlerò in un articolo dedicato), stabilire tra di loro la comunicazione, le dipendenze.

Spero tu abbia capito la potenza di questo strumento. Se hai ancora qualche dubbio, ho deciso di farti vedere un esempio, molto semplice, di docker-compose.yml. Installeremo WordPress.

Iniziamo subito!

Solito terminale alla mano, crea e posizionati in una directory a tua scelta e poi:

nano docker-compose.yml

Al suo interno scrivi le seguenti righe:

version: '3.3'

services:
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - ./wordpress_files:/var/www/html
    ports:
      - "80:80"
    restart: always
    environment: 
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: db_docker_wordpress
      WORDPRESS_TABLE_PREFIX: prefixtabelle_ 
      WORDPRESS_DB_USER: docker_wordpress
      WORDPRESS_DB_PASSWORD: scelgo_una_password_complessa!1

  db:
    container_name: db
    image: mysql:5.7
    volumes:
      - ./db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: scelgo_una_password_molto_complessa123!?
      MYSQL_DATABASE: db_docker_wordpress
      MYSQL_USER: docker_wordpress
      MYSQL_PASSWORD: scelgo_una_password_complessa!1

Salviamo: ctrl+x poi y ed Invio. Presta sempre attenzione all’indentazione, è fondamentale altrimenti rischi l’errata interpretazione da parte di docker-compose (quindi darà errore e non funzionerà nulla). YAML predilige l’indentazione con 2 spazi. Ti consiglio, infine, di scegliere delle password serie 😂

Ok, ma che ti ho fatto scrivere? Ti spiego:

  • version: '3.3': con questa riga stiamo definendo la sintassi che docker-compose deve aspettarsi di trovare nelle righe successive. Con il tempo sono state implementate nuove funzioni, nuovi tag e comandi. Puoi trovare l’elenco completo delle versioni a questo link. Se hai una versione precedente di Docker e/o docker-compose e vuoi utilizzare una sintassi recente, come indicato nella tabella di compatiilità, devi procedere all’aggiornamento;
  • services: con questo tag andiamo a definire la lista di tutti i servizi dell’applicazione. Nell’esempio sono 2: wordpress e db. Sono due nomi che ho scelto io, avrei potuto chiamarli Pippo e Paperino. Servono a me per identificarli all’interno del mio progetto;
  • depends_on: dice al container (in questo caso è definito solo per il container wordpress) che dipende da servizi offerti da altri container, quindi semplicemente il container che ha delle dipendenze si avvierà dopo che quelli elencati in questa lista saranno up & running;
  • image: con questo tag indico a Docker quale immagine deve scaricarsi per creare il container. Come ti dicevo prima, le immagini le puoi cercare su DockerHub (in questo caso io ho usato quella ufficiale di WordPress e quella di MySQL), o con la scrittura di un Dockerfile puoi definire le tue immagini custom anche a partire da immagini già esistenti. Devi indicare sia il nome dell’immagine che il numero di versione separati da : (nel mio caso ho indicato per WordPress l’ultima versione e per MySQL la versione 5.7);
  • restart: tramite questo tag vado a definire le politiche di riavvio del container. In questo caso ho specificato always per far si che il container venga automaticamente riavviato all’avvio di Docker o che si riavvii automaticamente in caso di crash;
  • environment: le variabili di ambiente che devo dare al container per “passargli” delle configurazioni, di solito preferisco definire un file separato, in cui elenco tutte le variabili di ambiente di cui necessito e lo icludo nel docker-compose.yml, però in questo esempio non avrebbe favorito la lettura del codice, quindi ho scritto tutto qui. Come fai a sapere tutte le variabili che devi passare al container? Semplice, RTFM! C’è tutto nella pagina della descrizione dell’immagine che hai scelto, molto spesso c’è anche qualche esempio di configurazione già pronta per l’uso;
  • ports: questo comando serve a “mappare” le porte del container con quelle della macchina fisica. Ricordati sempre di indicare prima la porta della macchina fisica e poi quella del container. Nel mio esempio ho scelto di esporre direttamente la porta 80 per WordPress, se avessi voluto utilizzare, per esempio, la 9090 avrei potuto scrivere:
ports:
  9090:80
  • volumes: è lecito chiedersi: “tutti i files che sono nel container, come li consulto? dove sono? come ne faccio un backup?” con questo tag posso mappare una directory del container con una directory della macchina fisica. Vale la stessa regola delle porte: indica prima il path locale e poi quello del container;
  • container_name: con questo tag vado a dare un nome al container con il quale posso identificarlo all’interno della “rete” di servizi che sto andando a creare. Mi spiego meglio: al container di WordPress ho dovuto passare tramite variabile di ambiente l’host del database, un container non ha un suo IP quindi gli ho assegnato un nome con il quale può essere identificato, infatti come valore della variabile WORDPRESS_DB_HOST ho passato db che è il nome che ho dato al container del database.

Ora hai la conoscenza 😄

Come avvio il tutto?

Un solo comando, facile e semplice da ricordare:

docker-compose up -d
  • il parametro -d è per farlo andare in modalità detached, cioè ti lascia la console libera subito dopo la sua esecuzione, diversamente avresti a video il log del container con la console impegnata.
root@docker-test:~# docker-compose up -d
Creating network "root_default" with the default driver
Creating volume "root_wordpress_files" with default driver
Creating volume "root_db_data" with default driver
Pulling db (mysql:5.7)...
5.7: Pulling from library/mysql
8559a31e96f4: Pull complete
d51ce1c2e575: Pull complete
c2344adc4858: Pull complete
fcf3ceff18fc: Pull complete
16da0c38dc5b: Pull complete
b905d1797e97: Pull complete
4b50d1c6b05c: Pull complete
d85174a87144: Pull complete
a4ad33703fa8: Pull complete
f7a5433ce20d: Pull complete
3dcd2a278b4a: Pull complete
Digest: sha256:32f9d9a069f7a735e28fd44ea944d53c61f990ba71460c5c183e610854ca4854
Status: Downloaded newer image for mysql:5.7
Pulling wordpress (wordpress:latest)...
latest: Pulling from library/wordpress
8559a31e96f4: Already exists
e0276193a084: Pull complete
eb2d00c10344: Pull complete
f54006e0dc29: Pull complete
e0d3d1244592: Pull complete
3a60f364b0c5: Pull complete
3e309988c00b: Pull complete
f65316e96b10: Pull complete
b22875b95a2a: Pull complete
0c78caf16ec3: Pull complete
4fc30aae7ee5: Pull complete
37b016cacdc6: Pull complete
fd56bf3cc539: Pull complete
b0ba72715b92: Pull complete
03888322beaa: Pull complete
7e7ce3c89644: Pull complete
f6556df913cf: Pull complete
11b2e0de50b5: Pull complete
1c79bd2495a6: Pull complete
0f2fb876982e: Pull complete
Digest: sha256:6f609ebf8518069516df36f0ab504735f8e563c1e303c37eba4902e732fcc6c6
Status: Downloaded newer image for wordpress:latest
Creating root_db_1 ... done
Creating root_wordpress_1 ... done
root@docker-test:~# 

Alla fine del processo, digitando ls -l, dovresti avere una cosa del genere:

root@docker-test:~# ls -l
total 12
drwxr-xr-x 6      999 root     4096 Jul 14 15:59 db_data
-rw-r--r-- 1 root     root      842 Jul 14 15:57 docker-compose.yml
drwxr-xr-x 5 www-data www-data 4096 Jul 14 16:08 wordpress_files
root@docker-test:~# 

Le cartelle db_data e wordpress_files sono quelle che abbiamo definito nel docker-compose.yml e contengono i file presenti all’interno dei container.

Se voglio cancellare i container preservando però i volumi?

root@docker-test:~# docker-compose down
Stopping root_wordpress_1 ... done
Stopping root_db_1        ... done
Removing root_wordpress_1 ... done
Removing root_db_1        ... done
Removing network root_default
root@docker-test:~#

E se invece voglio cancellare proprio tutto? Anche i files presenti nei volumi che ho creato?

root@docker-test:~# docker-compose down --volume
Stopping root_wordpress_1 ... done
Stopping root_db_1        ... done
Removing root_wordpress_1 ... done
Removing root_db_1        ... done
Removing network root_default
Removing volume root_wordpress_files
Removing volume root_db_data
root@docker-test:~#

Voglio farti notare un’ultima cosa. Se lancio il comando up una seconda volta, vedrai che l’output è più snello:

root@docker-test:~# docker-compose up -d
Creating network "root_default" with the default driver
Creating root_db_1 ... done
Creating root_wordpress_1 ... done
root@docker-test:~#

Questo perchè le immagini dei container le ha già tirate giù prima e le ha conservate, consentendoti di non doverle più riscaricare e di creare nuovi container dello stesso tipo istantaneamente. Puoi gestire le immagini da Portainer o da riga di comando (questo potrebbe essere un ulteriore articolo di approfondimento 🤔 valuterò).

Ti lascio qualche screen che ho realizzato, sia in locale che su server remoto, dell’installazione di WordPress.

Installazione di WordPress in locale con Docker
Installazione di WordPress in locale con Docker (click per ingrandire)
Installazione di WordPress su server remoto con Docker
Installazione di WordPress su server remoto con Docker (click per ingrandire)
WordPress homepage su server remoto con Docker
WordPress homepage su server remoto con Docker (click per ingrandire)

Spero di non aver perso la tua attenzione 😄 ora però dovresti essere in grado di capire un docker-compose.yml quando ne incontri uno e potresti anche azzardare a scriverne uno tutto tuo. Se hai problemi puoi scrivermi nei commenti o ai miei contatti.

A presto

AP

Antonio Porcelli @progressify

Antonio Porcelli

@progressify

Commenta l'articolo

Se non visualizzi il blocco dei commenti è perchè non hai accettato i cookies.
Cancella le preferenze del tuo browser per questo sito, aggiorna la pagina ed accetta i cookies.