Accelera le tue competenze con questa guida su Docker Compose

Se stai cercando come creare container Docker riproducibili con Docker Compose, sei nel posto giusto. In questo tutorial passo-passo su Docker Compose, imparerai come creare container semplici, mappare porte con Docker Compose fino a scenari multi-container complessi.

Sei pronto? Iniziamo!

Prerequisiti

Se desideri seguire passo-passo questo tutorial, assicurati di avere quanto segue:

  1. A fresh install of Ubuntu Server LTS with SSH Enabled. This guide will use Ubuntu Server LTS 20.04.1 as the Docker host machine.
  2. A computer with VS Code installed (optional). This guide will use Visual Studio Code 1.52.1 to SSH to the Docker host and run commands.
  3. L’estensione SSH ufficiale di VS Code installatae collegata all’host Docker. (opzionale)

Cos’è Docker Compose?

I comandi singoli possono diventare molto lunghi in Docker. Prendi ad esempio quello seguente. Questo esempio crea un container per un’applicazione software chiamata bookstack.

docker create \
   --name=bookstack \
   -e PUID # UID dell'utente che acquisirà la proprietà dell'applicazione/file \
   -e PGID # GID dell'utente che acquisirà la proprietà dell'applicazione/file \
   -e DB_USER # L'utente del database \
   -e DB_PASS # La password del database \
   -e DB_HOST # L'host del database \
   -e DB_DATABASE # Il database da utilizzare \
   -e APP_URL # L'URL su cui l'applicazione sarà accessibile (necessario per il corretto funzionamento del reverse proxy) \
   -v /host/path/to/config:/config # Posizione dei dati caricati \
   -p 80:80/tcp # Porta dell'interfaccia utente web \
   --restart unless-stopped \
   linuxserver/bookstack:version-v0.31.4

Man mano che la complessità di un ambiente Docker aumenta, aumenta anche il numero di flag e condizioni necessarie per una corretta configurazione del container. La riga di comando di Docker diventa sempre più ingombrante e difficile da risolvere; soprattutto quando si iniziano ad aggiungere configurazioni a più container.

Docker Compose è un modo per creare container Docker riproducibili utilizzando un file di configurazione anziché comandi Docker estremamente lunghi. Utilizzando un file di configurazione strutturato, gli errori sono più facili da individuare e le interazioni tra i container sono più facili da definire.

Docker Compose diventa rapidamente indispensabile quando si hanno dipendenze tra i container o si lavora con ambienti a più container.

Docker Compose è un modo fantastico per entrare nel mondo dell’Infrastruttura come Codice senza la complessità dei sistemi distribuiti come Kubernetes.

Docker Compose utilizza una struttura di file di configurazione chiamata YAML. YAML è simile a JSON o HTML nel senso che YAML è un linguaggio strutturato leggibile dalle macchine. YAML si concentra specificamente sull’essere il più leggibile possibile per gli esseri umani mantenendo al contempo il potere strutturato.

YAML ha uno svantaggio in cui le tabulazioni e altri spazi bianchi sono significativi e devono essere formattati correttamente. VS Code fa gran parte di questo lavoro per te ed è anche il motivo per cui vedrai molti degli esempi realizzati in VS Code.

Installazione di Docker Compose

Ora iniziamo a mettere le mani in pasta. Presumendo che tu sia connesso al tuo host Docker, è il momento di installare Docker Compose.

Docker Compose è un pacchetto separato rispetto all’esecuzione di Docker. Ma l’installazione di Docker Compose installerà anche l’esecuzione di Docker, quindi ucciderai due piccioni con una fava!

Per installare Docker Compose e l’esecuzione di Docker, esegui i seguenti due comandi.

# Aggiorna l'elenco del software (noto come repository) e quindi installa Docker Compose
# con tutte le dipendenze necessarie. L'opzione -y viene utilizzata per saltare la conferma
sudo apt update -y
sudo apt install docker-compose -y
The installation command for Docker Compose

Una volta installato, dovresti creare una struttura delle cartelle per archiviare i container.

Creazione di una struttura di cartelle per Docker Compose

Prima di poter creare un container con Docker Compose, devi prima creare una cartella per archiviare i container. Non dovresti solo creare una struttura delle cartelle per archiviare i container, ma scoprirai che vari comandi Docker sono sensibili alla posizione dei vari file di configurazione; Docker Compose non fa eccezione.

Il componente più importante di Docker Compose è il suo file di configurazione chiamato docker-compose.yaml. Questo file di configurazione, come spiegato in precedenza, indica come il runtime di Docker dovrebbe creare un container.

Quando esegui Docker Compose, il comando cercherà il suo file di configurazione nella stessa cartella in cui viene eseguito il comando. A causa di questo requisito, è sempre meglio creare una cartella separata quando si esegue Docker Compose.

Può esserci solo un file di configurazione Docker Compose per cartella.

Per dimostrare come creare un container Docker con Docker Compose, crea prima una struttura di cartelle per archiviare il futuro container e il relativo file di configurazione utilizzando un piccolo file server chiamato Caddy.

Caddy è un fileserver, simile a apache httpd o nginx, ma scritto nel linguaggio Go. Caddy è specificamente progettato per facilità d’uso (e genererà automaticamente o servirà un file index.html) senza configurazione. Questa combinazione rende Caddy una buona scelta per i principianti.

Assumendo di essere connesso all’host Docker, crea la struttura delle cartelle come segue:

  1. Nella tua directory home, crea una cartella chiamata containers. Questa cartella sarà un buon contenitore per questo ed altri container.
  2. All’interno della cartella containers, crea una sottocartella chiamata caddy. Questa cartella conterrà il file di configurazione Docker Compose e il container di Caddy.
  3. Infine, all’interno della cartella del container, caddy, crea un file di testo vuoto chiamato docker-compose.yaml che diventerà il file di configurazione Docker Compose.

Con la struttura delle cartelle e il file di configurazione Docker Compose creati, puoi ora iniziare a compilare il file di configurazione con una configurazione Docker Compose.

Creazione di un file di configurazione Docker Compose

Nella sua forma più basilare, un file docker-compose.yaml per il container di Caddy appare come segue. Nel tuo editor di testo Linux preferito o con VS Code, copia e incolla il codice qui sotto nel file di configurazione Docker Compose creato in precedenza.

version: "3.7"
services:
  caddy:
    container_name: "caddy"
    image: "caddy:latest"
    ports:
      - "80:80"

Passiamo attraverso ognuna delle opzioni mostrate:

  • versione specifica la versione del file docker-compose. Ogni nuova definizione di Docker Compose include cambiamenti radicali alla specifica. Pertanto, la versione è importante affinché Docker Compose possa capire quali funzionalità utilizzare. La versione 3.7 è l’ultima versione supportata da Ubuntu 20.04.1 LTS.

La specifica completa per Docker Compose 3.x può essere trovata qui. La documentazione collegata illustra ogni singola opzione che è possibile utilizzare con Docker Compose

  • servizi contiene le specifiche per i container effettivi. È possibile definire più container in questa sezione.
  • caddy è il nome del primo container (questo è puramente per riferimento).
  • container_name definisce il nome effettivo assegnato al container da Docker e deve essere unico.
  • image è il nome dell’immagine. In questo caso, viene definito caddy dal Docker Hub. Il nome o il numero dopo il tag separati da due punti è la versione.

Mappatura delle porte

In particolare, quest’ultima opzione richiede una menzione speciale:

ports:
  - "80:80"

In Docker Compose, la direttiva ports ti permette di impostare una o più mappature dalla macchina host al container. Ad esempio, sopra hai mappato la porta 80 sulla macchina host alla porta 80 del container. Tuttavia, non è necessario fare corrispondere il numero di porta. L’esempio seguente mappa la porta 8800 sulla macchina host alla porta 80 del container.

ports:
  - "8800:80"

Puoi anche definire più porte come mostrato di seguito.

ports:
  - "80:80"
  - "443:443"

In questo modo verranno mappate sia la porta 80 che 443 sulla macchina host (una configurazione comune per i server web, per servire sia HTTP che HTTPS).

Il creatore dell’immagine Docker definisce le porte disponibili al momento della creazione. Assicurati di controllare la documentazione dell’immagine con cui stai lavorando su Docker Hub o sul sito web del manutentore per le porte mappabili. Non ha senso mappare una porta se la porta non è in uso!

Tenendo presente ciò, vediamo come eseguire effettivamente il container.

Esecuzione del container

A questo punto dovresti avere il file docker-compose.yaml all’interno della cartella ~\containers\caddy. Ora è il momento di creare e avviare il container di Caddy.

Nel tuo terminale esegui il seguente comando che avvierà i container Docker definiti nel file docker-compose.yaml.

# Questo comando deve essere eseguito nella stessa cartella del file. L'opzione -d esegue
# il comando *detach*, che avvierà il container in background
sudo docker-compose up -d

Potresti notare che non hai dovuto specificare la posizione del file docker-compose.yaml quando hai eseguito sudo docker-compose up -d. Docker Compose si aspetta che tu esegua tutti i comandi all’interno della cartella che contiene il file docker-compose.yaml, poiché molti comandi sono relativi a quella cartella.

Ora verifica che il container sia attivo e in esecuzione navigando su http://<il tuo indirizzo IP>. Questa guida utilizza http://homelab-docker come riferimento.

Puoi vedere questo processo in azione in Visual Studio Code mentre sei connesso tramite SSH all’host Docker nell’animazione seguente:

Demonstrating a container created with Docker Compose

Successo! Hai utilizzato con successo Docker Compose per avviare un container da un file di configurazione. Con questo primo passo importante, vediamo ora come gestire lo stato del tuo container.

Comandi per Gestire i Container Separati

Nella sezione precedente, hai avviato il container caddy utilizzando il flag -d. In questo modo hai eseguito un container in uno stato separato. Quando un container è in uno stato separato, il container continua a essere in esecuzione in background. Ma questo pone un problema: come gestire quel container se non hai più un controllo diretto?

Per risolvere questo problema, Docker Compose dispone di una serie di comandi che gestiranno i container avviati con un file docker-compose.yaml:

  • docker-compose restart viene utilizzato per riavviare un container in esecuzione. Ciò è diverso dal riavvio effettivo di docker-compose up -d. Il comando di riavvio semplicemente riavvierà un container esistente, eseguirà nuovamente il comando docker-compose up -d e ricreerà il container da zero (se il file di configurazione è stato modificato).
  • docker-compose stop fermerà un container in esecuzione senza distruggerlo. Allo stesso modo, docker-compose start avvierà nuovamente il container.
  • docker-compose down fermerà i container in esecuzione e li distruggerà. Questo è dove entrano in gioco i collegamenti dei volumi (leggi di più di seguito).
  • docker-compose pull scaricherà la versione corrente dell’immagine Docker (o delle immagini) dal repository. Se si utilizza l’etichetta latest, è possibile seguire con docker-compose down && sudo docker-compose up -d per sostituire il container con l’ultima versione. L’utilizzo di docker-compose pull è un modo conveniente per aggiornare i container rapidamente con un tempo di inattività minimo.
  • docker-compose logs mostrerà i log del container in esecuzione (o fermo). È anche possibile indirizzare singoli container (se sono definiti più container nel file di composizione) con docker-compose logs <nome del container>.

A full list of docker-compose commands can be seen by running docker-compose with no additional arguments or referenced here in the documentation.

Ora che hai un container in esecuzione, vediamo come utilizzare il contenuto salvato localmente sul tuo computer.

Creazione di collegamenti dei volumi in Docker Compose.

I Bind Mount sono il modo in cui Docker mappa i dati utente importanti su una memoria locale nel tuo server. Per iniziare, genera del contenuto da ospitare nel contenitore:

  1. Sul server Docker, all’interno della cartella ~/containers/caddy crea una nuova cartella chiamata files.

2. Crea un nuovo file chiamato index.html all’interno della cartella ~/containers/caddy che assomigli a quello riportato di seguito. Questa sarà la pagina principale che il server web Caddy servirà.

<body><h2>hello world!</h2></body>

3. Modifica il tuo file di configurazione di Docker Compose come indicato di seguito. L’esempio di file sottostante aggiunge la sezione volumes e indica un bind mount alla cartella files appena creata per renderla disponibile al contenitore.

version: "3.7" services: caddy: container_name: "caddy" image: "caddy:latest" ports: - "80:80" volumes: #il ./ si riferisce a una cartella relativa al file docker-compose - "./files:/usr/share/caddy"

4. Esegui nuovamente il comando docker-compose up -d. Docker Compose riconoscerà che il file è stato modificato e ricreerà il tuo contenitore.

5. Accedi alla pagina del contenitore tramite un browser e dovresti vedere che viene servita la pagina “Hello World!”

Puoi vedere quanto segue nell’animazione sottostante:

Creating a bind mount using Docker Compose

Ora stai ospitando il contenuto memorizzato localmente sulla tua macchina! Tuttavia, cosa succede se il tuo contenuto è su una fonte esterna come una condivisione di rete?

Utilizzando Docker Compose con Docker Volumes

Una volta creato un semplice contenitore con Docker Compose, probabilmente avrai bisogno che il contenitore possa accedere a file presenti altrove, magari su una condivisione di rete. In tal caso, puoi configurare il contenitore per utilizzare i volumi di Docker direttamente nel file di configurazione di Docker Compose.

A scopo dimostrativo, questa guida creerà un server Network File Share (NFS) sull’host Docker. L’utilizzo di contenuto locale come mount NFS non ha una finalità pratica al di fuori della dimostrazione. Se desideri montare un volume NFS, di solito sarà da una fonte esterna come un NAS o un server remoto.

Configurazione di una condivisione NFS

Se non hai già configurato una condivisione NFS, crea una ora sull’host Docker per questo tutorial. Ecco come fare:

  1. 1. Installa il pacchetto NFS server eseguendo il comando apt install nfs-kernel-server -y.

2. Aggiungi il contenitore come esportazione NFS (simile a una condivisione CIFS di Windows) eseguendo il seguente comando.

# Aggiungi una riga al file di configurazione /etc/exports per creare una condivisione NFS per # /home/homelab/containers. Questa condivisione è esposta solo a localhost (per # impedire che altri computer vi accedano) echo '/home/homelab/containers localhost(rw,sync,no_root_squash,no_subtree_check)' | sudo tee -a /etc/exports # Riavvia il server NFS con la nuova configurazione sudo systemctl restart nfs-kernel-server

3. Ora verifica che l’host esponga la condivisione NFS eseguendo il comando showmount -e localhost. Questo comando mostrerà tutte le condivisioni NFS attualmente esposte e chi ha accesso.

Nella schermata sottostante, puoi vedere che /home/homelab/containers è esposto, ma solo al computer localhost (che è lo stesso server in esecuzione come host Docker).

Creating a NFS share in Ubuntu 20.04

Se vedi la cartella /home/<username>/containers nell’output, significa che la condivisione NFS è stata configurata.

Definizione di un Named Volume di Docker

Dopo aver creato la condivisione NFS, devi ora dire a Docker come accedere a quella condivisione. Utilizzando Docker Compose, puoi farlo definendo un named volume nel file di configurazione di Docker Compose.

A named volume is a way for Docker to abstract network-based file shares. Network file sharing comes in all sorts of shapes and sizes these days: CIFS (windows) shares, NFS (Linux) shares, AWS S3 Buckets, and more. By creating a Named Volume, Docker does the hard part of figuring out how to talk to the network share and lets the container just treat the share as if it is local storage.

Per creare un named volume:

  1. Apri il file di configurazione di Docker Compose (docker-compose.yaml). Se stai seguendo, il file dovrebbe trovarsi nella cartella ~/containers/caddy.

2. All’interno del file di configurazione di Docker Compose, aggiungi una sezione volumes dopo la sezione services. Il tuo file di configurazione dovrebbe apparire come segue. La sezione volumes crea un named volume chiamato MyWebsite. All’interno di quel named volume, vengono specificati i parametri necessari (come l’IP, le impostazioni NFS e il percorso). Anche il parametro volumes all’interno della sezione services viene modificato per puntare al named volume anziché a una cartella locale.

version: "3.7"
 services:
   caddy:
     container_name: "caddy"
     image: "caddy:latest"
     ports:
       - "80:80"
     volumes:
       - "MyWebsite:/usr/share/caddy"
 volumes:
   MyWebsite:
     driver_opts:
       type: "nfs"
       o: "addr=localhost,nolock,soft,rw"
       device: ":/home/homelab/containers/caddy/files"

3. Una volta definito il volume nominato che punta alla condivisione NFS nel file di configurazione Docker Compose, eseguire docker-compose up -d per creare e avviare il contenitore. Se tutto va bene, il contenitore e il sito web dovrebbero tornare attivi.

Setting NFS client settings within Docker Compose in VS Code

4. Navigare nuovamente alla pagina del contenitore. Il contenuto di index.html dovrebbe apparire come se il file fosse montato localmente. Tuttavia, quel file viene montato tramite il server NFS configurato in rete.

Demonstrating access to the index.html file through an NFS share in Docker

Ora che è possibile montare volumi Docker esterni in Docker Compose, è possibile utilizzare vari tipi di archiviazione di rete nei propri contenitori. Tuttavia, Docker Compose può fare molto di più che definire singoli contenitori o volumi. Approfondiamo scenari complessi con contenitori multipli.

In questo tutorial non utilizzeremo più il contenitore caddy, quindi è possibile rimuoverlo utilizzando docker-compose down.

Definizione di contenitori multipli in Docker Compose

La maggior parte dei contenitori Docker non funziona isolatamente. I contenitori Docker di solito hanno dipendenze di servizio come database o servizi web separati che comunicano tramite un’API.

Utilizzando Docker Compose, è possibile raggruppare contenitori definiti all’interno di un singolo file. Definendo contenitori multipli in un singolo file, i contenitori possono comunicare tra servizi dipendenti e semplificare l’organizzazione di layout di contenitori complessi.

Per dimostrare uno scenario del genere, configuriamo un’applicazione wiki popolare chiamata BookStack.

BookStack è un software wiki popolare conosciuto per la sua facilità d’uso e la sua struttura gerarchica (a differenza di una struttura piatta, come ad esempio mediawiki).

BookStack, come molte applicazioni web, richiede un database separato per funzionare correttamente, così come le informazioni necessarie per comunicare con il database. Configurare una tale situazione è dove Docker Compose eccelle.

Crea il file di configurazione Docker Compose

BookStack non ha un’immagine Docker mantenuta internamente, tuttavia, linuxserver.io mantiene un’immagine Docker Hub affidabile per conto di BookStack. Mentre la documentazione sul sito di Docker Hub ha un file di configurazione Docker Compose consigliato, questo tutorial creerà un nuovo file di configurazione spiegando i concetti.

Sull’host Docker:

  1. Innanzitutto, crea una cartella per BookStack. Se hai seguito i tutorial della sezione precedente, dovresti avere una cartella ~/containers. Crea una cartella chiamata bookstack all’interno di questa cartella.

2. Quindi crea un file di configurazione Docker Compose vuoto chiamato docker-compose.yaml all’interno della cartella bookstack.

Creating the folder structure for Bookstack in VS Code

3. Ora apri il file di configurazione Docker Compose e definisci due container: il container bookstack e il container bookstack_db (mariadb).

version: "3.7"
 services:
   bookstack:
     container_name: "bookstack"
     image: "ghcr.io/linuxserver/bookstack"
     ports:
       - "8080:80"
     volumes:
       - "./files:/usr/share/caddy"
     depends_on:
       - "bookstack_db"
   bookstack_db:
     container_name: "bookstack_db"
     image: "mariadb"
     volumes:
       - "./db:/var/lib/mysql"

Finora, questo file docker-compose.yaml utilizza principalmente concetti già introdotti: hai due servizi (bookstack e bookstack_db), entrambi con immagini e bind mounts. Il contenitore di bookstack ha una mappatura delle porte dalla porta dell’host 8080 alla porta interna 80.

Dato il bassissimo overhead dei contenitori Docker, è pratica comune definire un contenitore del database separato per ogni applicazione web. Ciò consente una maggiore separazione dei compiti. Questo è nettamente diverso dalle configurazioni tradizionali del database, in cui una singola installazione del database può servire centinaia di applicazioni web.

Una nuova opzione che puoi vedere nel file sopra è il comando depends_on. Questo comando indica a Docker l’ordine in cui i contenitori devono avviarsi. Definendo il comando depends_on, dici a Docker che il contenitore bookstack_db deve avviarsi per primo.

Configurazione della comunicazione tra i contenitori tramite variabili d’ambiente

Questo file di configurazione creato nell’ultima sezione non è ancora completo. Sebbene tu abbia definito due servizi (contenitori), non stanno comunicando tra loro! Il contenitore di bookstack non sa come comunicare con il contenitore di bookstack_db. Risolviamo questo problema utilizzando le variabili d’ambiente.

Le variabili d’ambiente sono il modo più comune di fornire variabili ai contenitori Docker. Queste sono variabili fornite durante l’esecuzione (o definite nel file di configurazione docker-compose.yaml) per fornire informazioni su ciò che il contenitore deve fare.

Le variabili d’ambiente sono definite dalla persona che crea l’immagine Docker. Saranno diverse a seconda dell’immagine Docker che stai usando e devi fare riferimento alla documentazione del creatore per sapere quali variabili d’ambiente utilizzare.

Ci sono due metodi per definire le variabili d’ambiente: direttamente nel file docker-compose.yaml stesso o come file separati.

A separate file is, typically, the recommended method, especially if variables contain sensitive data such as passwords. A docker-compose.yaml file is designed to be shared or even uploaded to a public-facing GitHub repo. Having a separate file for sensitive data reduces the chance of an accidental security breach.

Nell’host Docker, crea ora due variabili d’ambiente: una per il container bookstack e una per il container bookstack_db.

  1. Crea un nuovo file nella cartella ~/containers/bookstack chiamato bookstack.env con il seguente contenuto:
APP_URL is the IP address or hostname of your server. This article is using homelab-docker
 APP_URL=http://homelab-docker:8080
 DB_HOST is the container name you gave your container
 DB_HOST=bookstack_db
 DB_USER is defined in the bookstack_DB environment file
 DB_USER=bookstack_user
 DB_PASS is also defined in the bookstack_DB environment file
 DB_PASS=MySecurePassword
 DB_DATABASE is the name of the database within mariadb
 DB_DATABASE=bookstack

2. Crea un nuovo file nella cartella ~/containers/bookstack chiamato bookstack_db.env e includi il seguente contenuto:

The root password for our database, keep it secret, keep it safe
 MYSQL_ROOT_PASSWORD=MySecureRootPassword
 The database bookstack will be using
 MYSQL_DATABASE=bookstack
 the user bookstack will be using
 MYSQL_USER=bookstack_user
 the password bookstack will be using
 MYSQL_PASSWORD=MySecurePassword

3. Come pratica consigliata, assicurati ora che entrambi i file env non siano leggibili da altri utenti.

chmod 600 bookstack.env bookstack_db.env

Dovresti cambiare l’accesso in lettura perché sia il file bookstack.env che il file bookstack_db.env contengono dati sensibili.

4. Aggiorna il file Docker Compose ~/containers/bookstack/docker-compose.yaml per fare riferimento a questi due file di ambiente come mostrato di seguito.

version: "3.7"
 services:
   bookstack:
     container_name: "bookstack"
     image: "ghcr.io/linuxserver/bookstack"
     ports:
       - "8080:80"
     volumes:
       - "./files:/usr/share/caddy"
     depends_on:
       - "bookstack_db"
     env_file:
       - "./bookstack.env"
   bookstack_db:
     container_name: "bookstack_db"
     image: "mariadb"
     volumes:
       - "./db:/var/lib/mysql"
     env_file:
       - "./bookstack_db.env"

5. Ora avvia i container bookstack e bookstack_db utilizzando Docker Compose.

sudo docker-compose up -d

Puoi vedere ciascuno dei passaggi sopra eseguiti in questa sezione eseguita in VS Code qui sotto.

Setting up environment variables and the Docker Compose file with VS Code

Monitoraggio dei log di Docker Compose

Il motore Docker funziona con Docker Compose per eseguire molte diverse attività in background. È utile poter monitorare ciò che sta accadendo, specialmente quando si lavora contemporaneamente con più container.

Per monitorare il container bookstack, ad esempio, utilizzare il comando logs. In questo tutorial, una volta visualizzati i log che mostrano [services.d] done, è possibile accedere all’URL di bookstack.

sudo docker-compose logs bookstack
Using the docker-compose logs command
The bookstack welcome screen. Default login is [email protected]/password

A questo punto, dovresti avere un wiki completamente funzionante in esecuzione all’interno del suo stesso container, con il suo database, interamente all’interno di Docker!

Finché hai le cartelle bookstack e bookstack_db, puoi ricreare il tuo ambiente bookstack da zero.

Docker Compose e Networking

Fino a questo punto, non hai imparato molto sull’aspetto della comunicazione e della rete di come i container lavorano insieme. Cambiamo questo.

Quando crei più container all’interno di un singolo file docker-compose.yaml, come hai fatto nelle sezioni precedenti, vengono tutti assegnati alla stessa rete (solitamente chiamata nome-della-cartella-genitore_default).

Puoi vedere la rete creata per i container quando esegui docker-compose up -d come mostrato di seguito.

The default network created with docker-compose comes up

Quando tutti i container vengono assegnati alla stessa rete, Docker crea voci DNS per loro internamente. Ecco perché nell’esempio precedente hai fatto riferimento al tuo database come bookstack_db nelle variabili d’ambiente. Quel nome bookstack_db è in realtà un’entrata DNS che punta all’indirizzo IP del container del database.

Non è necessario fare affidamento su Docker Compose per generare automaticamente le reti. È possibile definire manualmente reti interne o esterne. La definizione manuale delle reti è ottima quando si ha un contenitore che deve comunicare con un altro contenitore in un file docker-compose.yaml separato. È possibile esporre le porte o creare una rete alla quale possono entrambi unirsi!

Si noti che quando si inizia a definire esplicitamente le reti, è necessario definire esplicitamente anche la rete predefinita. Docker Compose smetterà di creare automaticamente quella rete una volta che si inizia a definire le reti

Ora modifica il file docker-compose.yaml di BookStack per includere una rete creata esternamente.

  1. Crea la rete esterna con il comando docker network create my_external_network.

2. Definisci la rete esterna nel file docker-compose.yaml:

version: "3.7"
 services:
   bookstack:
     container_name: "bookstack"
     image: "ghcr.io/linuxserver/bookstack"
     ports:
       - "8080:80"
     volumes:
       - "./files:/usr/share/caddy"
     depends_on:
       - "bookstack_db"
     env_file:
       - "./bookstack.env"
     networks:
       - "my_external_network"
       - "bookstack_default"
   bookstack_db:
     container_name: "bookstack_db"
     image: "mariadb"
     volumes:
       - "./db:/var/lib/mysql"
     env_file:
       - "./bookstack_db.env"
     networks:
       - "bookstack_default"
 networks:
   bookstack_default:
   my_external_network:
     external: true

3. Esegui il comando docker-compose up -d per ricreare i contenitori. I tuoi due contenitori sono ora collegati a due reti come mostrato di seguito.

A highlight of the networks defined within a docker-compose file

Il contenitore di BookStack è ora anche collegato a una rete definita esternamente. Ciò consente di creare un altro contenitore che trasforma il traffico HTTP di BookStack in HTTPS prima che esca da Docker (chiamato reverse-proxy).

Impostare un utente specifico per eseguire un contenitore.

Di default, tutti i container Docker vengono eseguiti come utente root in modalità sandbox. Questo equivale ad eseguire una macchina virtuale con l’utente amministratore predefinito. Sebbene questo in generale non sia un problema, ci sono preoccupazioni per la sicurezza se la sandbox viene compromessa.

Un altro problema nell’esecuzione come root riguarda i permessi dei file. Potresti notare che se provi a eliminare la cartella db all’interno della cartella bookstack, in realtà non puoi farlo; i contenuti sono di proprietà di root.

Anche se la maggior parte delle immagini non supporta l’esecuzione come utente non-root, le immagini di linuxserver.io in particolare offrono una variabile d’ambiente per impostare l’utente che viene eseguito all’interno del container. Puoi farlo aggiungendo UID=1000 e GID=1000 nella configurazione di bookstack.env.

1000:1000 è l’ID utente e di gruppo predefinito per il primo utente in Ubuntu (che potresti non essere tu). Puoi leggere ulteriori informazioni sugli ID utente e di gruppo su Correlato: Un Windows Guy in un Mondo Linux: Utenti e Permessi dei File)

Puoi anche forzare un UID e un GID utilizzando il parametro user in docker-compose, ma non è consigliato poiché la maggior parte dei container non si comporta correttamente quando viene imposto un utente diverso

Impostando la politica di ripristino

Se desideri che i contenitori creati con Docker Compose si riavvino in caso di errore, utilizza la politica di riavvio aggiungendo il parametro restart: <opzione> nelle impostazioni del contenitore nel file docker-compose.yaml.

restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

Aggiungendo questo parametro, i contenitori verranno riavviati automaticamente in caso di errore per mantenere l’uptime in caso di problemi di alimentazione imprevisti.

Impostazione manuale degli ingressi DNS per i contenitori

Come per Windows e Linux, anche Docker dispone di un “file hosts”. Utilizzando il parametro extra_hosts in un file di configurazione, puoi forzare un host a risolvere un indirizzo IP specifico. Questo può essere utile quando hai vincoli DNS, come DNS split o un server di test con cui desideri interagire temporaneamente.

extra_hosts:
  - "somehost:x.x.x.x"
  - "otherhost:x.x.x.x"

Esecuzione di comandi

Dopo l’avvio del contenitore, puoi eseguire comandi all’interno del contenitore utilizzando il comando docker-compose run. Ad esempio, potresti voler avviare un terminale Bash all’interno del tuo contenitore bookstack. Per farlo, esegui il comando qui sotto.

docker-compose run web bash

Conclusione

A questo punto, dovresti avere abbastanza informazioni per seguire la maggior parte dei tutorial su docker-compose disponibili sul web. Avere questa conoscenza può ampliare notevolmente la tua capacità di entrare nel mondo di Docker e nella creazione di app web con Infrastructure as Code.

Source:
https://adamtheautomator.com/docker-compose-tutorial/