Docker Compose: dallo sviluppo alla produzione

La traduzione della trascrizione del podcast è stata preparata in vista dell'inizio del corso «Amministratore Linux»

Docker Compose: dallo sviluppo alla produzione

Docker Compose è uno strumento straordinario per creare un ambiente di lavoro
per lo stack utilizzato nella tua applicazione. Ti permette di definire
ogni componente della tua applicazione, seguendo una sintassi chiara e semplice in YAML-
file
.

Con l'arrivo di docker compose v3 questi file YAML possono essere utilizzati direttamente nell'ambiente di lavoro, quando si lavora con
un cluster Docker Swarm.

Ma significa che puoi utilizzare lo stesso file docker-compose nel
processo di sviluppo e in ambiente di produzione? O utilizzare lo stesso file per
lo staging? Beh, in generale sì, ma per questa funzionalità abbiamo bisogno di quanto segue:

  • Interpolazione delle variabili: utilizzare variabili d'ambiente per alcuni
    valori che cambiano in ogni ambiente.
  • Sovrascrittura della configurazione: la possibilità di definire un secondo (o qualsiasi
    altro file docker-compose successivo) che modificherà qualcosa rispetto
    al primo, e docker compose si occuperà della fusione dei due file.

Differenze tra file per sviluppo e produzione

Durante lo sviluppo, probabilmente vorrà controllare le modifiche al codice in
modalità in tempo reale. Per fare questo, in genere, il volume con il codice sorgente viene montato in
un contenitore che ospita il runtime per la tua applicazione. Tuttavia, per l'ambiente di produzione
questo metodo non è adatto.

In produzione hai un cluster con più nodi, e il volume è locale rispetto al
nodo su cui è in esecuzione il tuo contenitore (o servizio), quindi non puoi
montare il codice sorgente senza operazioni complesse che includono
la sincronizzazione del codice, segnali, ecc.

Invece, di solito vogliamo creare un'immagine con una versione specifica del tuo codice.
Di solito viene contrassegnata con un tag appropriato (puoi utilizzare la semantica
versionamento o un altro sistema a tua discrezione).

Sovrascrittura della configurazione

Considerando le differenze e il fatto che le tue dipendenze possono variare tra gli scenari
di sviluppo e produzione, è chiaro che avremo bisogno di file di configurazione diversi.

Docker Compose supporta la fusione di diversi file compose per
ottenere la configurazione finale. Come funziona questo può essere visto con un esempio:

$ cat docker-compose.yml
version: "3.2"

services:
  whale:
    image: docker/whalesay
    command: ["cowsay", "hello!"]
$ docker-compose up
Creating network "composeconfigs_default" with the default driver
Starting composeconfigs_whale_1
Attaching to composeconfigs_whale_1
whale_1  |  ________
whale_1  | 
whale_1  |  --------
whale_1  |     
whale_1  |      
whale_1  |       
whale_1  |                     ##        .
whale_1  |               ## ## ##       ==
whale_1  |            ## ## ## ##      ===
whale_1  |        /""""""""""""""""___/ ===
whale_1  |   ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
whale_1  |        ______ o          __/
whale_1  |                     __/
whale_1  |           __________/
composeconfigs_whale_1 exited with code 0

Come già detto, docker compose supporta la fusione di più file compose,
consentendo di sovrascrivere diversi parametri in un secondo file. Ad esempio:

$ cat docker-compose.second.yml
version: "3.2"
services:
  whale:
    command: ["cowsay", "bye!"]

$ docker-compose -f docker-compose.yml -f docker-compose.second.yml up
Creating composeconfigs_whale_1
Attaching to composeconfigs_whale_1
whale_1  |  ______
whale_1  | 
whale_1  |  ------
whale_1  |     
whale_1  |      
whale_1  |       
whale_1  |                     ##        .
whale_1  |               ## ## ##       ==
whale_1  |            ## ## ## ##      ===
whale_1  |        /""""""""""""""""___/ ===
whale_1  |   ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
whale_1  |        ______ o          __/
whale_1  |                     __/
whale_1  |           __________/
composeconfigs_whale_1 exited with code 0

Tale sintassi non è molto comoda durante lo sviluppo, quando il comando
deve essere eseguito più volte.

Fortunatamente, docker compose cerca automaticamente un file speciale chiamato
docker-compose.override.yml per sovrascrivere i valori docker-compose.yml. Se
rinominare il secondo file produce lo stesso risultato, ma usando il comando originale:

$ mv docker-compose.second.yml docker-compose.override.yml
$ docker-compose up
Inizio composeconfigs_whale_1
Collegamento a composeconfigs_whale_1
whale_1  |  ______
whale_1  | 
whale_1  |  ------
whale_1  |     
whale_1  |      
whale_1  |       
whale_1  |                     ##        .
whale_1  |               ## ## ##       ==
whale_1  |            ## ## ## ##      ===
whale_1  |        /""""""""""""""""___/ ===
whale_1  |   ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
whale_1  |        ______ o          __/
whale_1  |                     __/
whale_1  |           __________/
composeconfigs_whale_1 è uscito con codice 0

Bene, è più facile ricordarlo così.

Interpolazione delle variabili

I file di configurazione supportano l'interpolazione
variabili
e i valori predefiniti. Quindi puoi fare quanto segue:

services:
  my-service:
    build:
      context: .
    image: private.registry.mine/my-stack/my-service:${MY_SERVICE_VERSION:-latest}
...

E se esegui docker-compose build (o push) senza la variabile d'ambiente
$MY_SERVICE_VERSION, verrà utilizzato il valore latest, ma se imposti
il valore della variabile d'ambiente prima della costruzione, sarà utilizzato durante la costruzione o il push
nel registro private.registry.mine.

I miei principi

Gli approcci che sono comodi per me possono essere utili anche a voi. Seguo queste
semplici regole:

  • Tutti i miei stack per produzione, sviluppo (o altri ambienti) sono definiti tramite
    file docker-compose.
  • I file di configurazione necessari per coprire tutti i miei ambienti minimizzano
    al massimo le duplicazioni.
  • Ho bisogno di un semplice comando per lavorare in ogni ambiente.
  • La configurazione principale è definita nel file docker-compose.yml.
  • Le variabili d'ambiente vengono utilizzate per definire i tag delle immagini o altre
    variabili che possono cambiare da ambiente a ambiente (staging, integrazione,
    produzione).
  • I valori delle variabili per la produzione sono utilizzati come valori di default,
    minimizzando i rischi nel caso di avvio dello stack in produzione senza
    una variabile d'ambiente impostata.
  • Per avviare il servizio in ambiente di produzione si utilizza il comando docker stack deploy --compose-file docker-compose.yml --with-registry-auth my-stack-name.
  • L'ambiente di lavoro si avvia con il comando docker-compose up -d.

Diamo un'occhiata a un semplice esempio.

# docker-compose.yml
...
services:
  my-service:
    build:
      context: .
    image: private.registry.mine/my-stack/my-service:${MY_SERVICE_VERSION:-latest}
    environment:
      API_ENDPOINT: ${API_ENDPOINT:-https://production.my-api.com}
...

E

# docker-compose.override.yml
...
services:
  my-service:
    ports: # This is needed for development!
      - 80:80
    environment:
      API_ENDPOINT: https://devel.my-api.com
    volumes:
      - ./:/project/src
...

Posso utilizzare docker-compose (docker-compose up), per avviare lo stack in
modalità di sviluppo con il codice sorgente montato in /project/src.

Posso utilizzare gli stessi file in produzione! E potrei usare esattamente
lo stesso file docker-compose.yml per lo staging. Per implementarlo in
produzione, devo semplicemente costruire e inviare l'immagine con un tag predefinito
nella fase CI:

export MY_SERVICE_VERSION=1.2.3
docker-compose -f docker-compose.yml build
docker-compose -f docker-compose.yml push

In produzione, può essere avviato con i seguenti comandi:

export MY_SERVICE_VERSION=1.2.3
docker stack deploy my-stack --compose-file docker-compose.yml --with-registry-auth

E se vuoi fare lo stesso nello staging, devi semplicemente definire
le variabili d'ambiente necessarie per funzionare nell'ambiente di staging:

export MY_SERVICE_VERSION=1.2.3
export API_ENDPOINT=http://staging.my-api.com
docker stack deploy my-stack --compose-file docker-compose.yml --with-registry-auth

In conclusione, abbiamo utilizzato due diversi file docker-compose, che senza
duplicare le configurazioni possono essere usati in qualsiasi tuo ambiente!

Scopri di più sul corso «Amministratore Linux»

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster