Quando si utilizza Docker per containerizzare le applicazioni, è prassi comune eseguire ciascun componente dell'applicazione in un container separato. Ad esempio, un sito Web potrebbe avere un server Web, un'applicazione e un database, ciascuno in esecuzione nel proprio contenitore.
Configurare i contenitori per comunicare tra loro e la macchina host può essere una sfida. Questa guida utilizzerà una semplice app di esempio per dimostrare le basi della comunicazione del container Docker. L'app sarà composta da un'app Node.js che legge i dati da un database PostgreSQL.
Prima di iniziare
Installa Docker CE
Avrai bisogno di un Linode con Docker CE installato per seguire i passaggi di questa guida.
Per installare Docker CE (Community Edition), segui le istruzioni all'interno di una delle guide seguenti:
-
Installazione e utilizzo di Docker su Ubuntu e Debian
-
Installazione e utilizzo di Docker su CentOS e Fedora
Per istruzioni complete su ancora più distribuzioni Linux, fai riferimento alla sezione Install Docker Engine della documentazione ufficiale di Docker.
Esempio di applicazione Node.js
L'app di esempio utilizzata in questa guida sarà una semplice app Node.js che leggerà "Hello world" da un database PostgreSQL e lo stamperà sulla console. In questa sezione creerai e testerai l'app sul tuo Linode senza utilizzare contenitori.
Installa e configura PostgreSQL
-
Aggiorna il tuo sistema:
sudo apt update && sudo apt upgrade
-
Installa PostGreSQL:
sudo apt install postgresql postgresql-contrib
-
Cambia il
postgres
password utente:sudo passwd postgres
-
Imposta una password per
postgres
utente del database:su - postgres psql -d template1 -c "ALTER USER postgres WITH PASSWORD 'newpassword';"
-
Crea un database per l'app di esempio e connettiti ad esso:
createdb nodejs psql nodejs
-
Aggiungi "Hello world" al database:
nodejs=# CREATE TABLE hello (message varchar); nodejs=# INSERT INTO hello VALUES ('Hello world'); nodejs=# \q
-
Crea un dump del database per un uso successivo:
pg_dumpall > backup.sql
-
Esci come
postgres
Utente Linux:exit
-
Copia il dump dei dati nella tua home directory:
sudo cp /var/lib/postgresql/backup.sql ~/.
-
Poiché ti connetterai a questo database da un container (che avrà un indirizzo IP diverso da
locahost
), dovrai modificare il file di configurazione di PostgreSQL per consentire le connessioni da indirizzi remoti. Apri/etc/postgresql/9.5/main/postgresql.conf
in un editor di testo. Decommenta illisten_addresses
riga e impostarlo su '*':- File:/ etc/postgresql/9.5/main/postgresql.conf
1 2 3 4 5 6 7
#------------------------------------------------------------------------------ # CONNECTIONS AND AUTHENTICATION #------------------------------------------------------------------------------ # - Connection Settings - listen_addresses = '*' # what IP address(es) to listen on;
-
Abilita e avvia il
postgresql
servizio:sudo systemctl enable postgresql sudo systemctl start postgresql
Crea un'app Hello World
-
Installa Nodo e NPM:
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - sudo apt-get install nodejs
-
Passa alla directory home e crea una directory:
cd mkdir app && cd app
-
Usando un editor di testo, crea
app.js
e aggiungi il seguente contenuto:- File:app .js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
const { Client } = require('pg') const client = new Client({ user: 'postgres', host: 'localhost', database: 'nodejs', password: 'newpassword', port: 5432 }) client.connect() client.query('SELECT * FROM hello', (err, res) => { console.log(res.rows[0].message) client.end() })
Questa app utilizza il
pg
Modulo NPM (node-postgres) per connettersi al database creato nella sezione precedente. Quindi interroga la tabella "hello" (che restituisce il messaggio "Hello world") e registra la risposta alla console. Sostituisci'newpassword'
con ilpostgres
password utente del database che hai impostato nella sezione precedente.Nota Il
pg
modulo può anche utilizzare variabili di ambiente per configurare la connessione client. Questa è l'opzione consigliata per le app di produzione. Maggiori informazioni sulle variabili di ambiente nella documentazione di thenode-postgres. -
Installa il
pg
modulo:npm install pg
-
Prova l'app:
node app.js
Se il database è configurato correttamente, sulla console verrà visualizzato "Hello world".
Collega il container all'host Docker
Questa sezione illustra un caso d'uso in cui l'app Node.js viene eseguita da un contenitore Docker e si connette a un database in esecuzione sull'host Docker.
Imposta il contenitore Docker
-
Torna alla tua home directory:
cd
-
Crea un Dockerfile per eseguire l'app Node.js:
- File:Dockerfile
1 2 3 4 5 6 7
FROM debian RUN apt update -y && apt install -y gnupg curl RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && apt install -y nodejs COPY app/ /home/ ENTRYPOINT tail -F /dev/null
-
L'immagine creata da questo Dockerfile copierà l'
app/
directory nella nuova immagine. Modificaapp.js
per consentire all'app di connettersi aldatabase
host invece dilocalhost
:- File:app /app.js
1 2 3 4 5 6 7
const client = new Client({ user: 'postgres', host: 'database', database: 'nodejs', password: 'newpassword', port: 5432 })
-
Crea un'immagine dal Dockerfile:
docker build -t node_image .
Collega il contenitore al database
-
Docker imposta automaticamente una rete bridge predefinita , accessibile tramite la
docker0
interfaccia di rete. Usaifconfig
oip
per visualizzare questa interfaccia:ifconfig docker0
L'output sarà simile al seguente:
L'indirizzo IP interno dell'host Docker (il tuo Linode) è 172.17.0.1.docker0 Link encap:Ethernet HWaddr 02:42:1e:e8:39:54 inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:1eff:fee8:3954/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:3848 errors:0 dropped:0 overruns:0 frame:0 TX packets:5084 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:246416 (246.4 KB) TX bytes:94809688 (94.8 MB)
-
Consenti a PostgreSQL di accettare connessioni dall'interfaccia Docker. Apri
/etc/postgresql/9.5/main/pg_hba.conf
in un editor di testo e aggiungi la seguente riga:- File:/ etc/postgresql/9.5/main/pg_hba.conf
1
host all postgres 172.17.0.0/16 password
Poiché 172.17.0.1 è l'IP dell'host Docker, tutti i contenitori sull'host avranno un indirizzo IP nell'intervallo 172.17.0.0/16.
-
Riavvia il database:
sudo systemctl restart postgresql
-
Avvia il contenitore:
docker run -d --add-host=database:172.17.0.1 --name node_container node_image
Il
--add-host
l'opzione definisce undatabase
host, che punta all'indirizzo IP dell'host Docker. Dichiarazione deldatabase
host in fase di esecuzione, anziché codificare l'indirizzo IP nell'app, aiuta a mantenere il contenitore riutilizzabile. -
Dall'interno del contenitore, usa
ping
per testare la connessione aldatabase
ospite:docker exec -it node_container ping database
-
A ogni container Docker viene assegnato anche il proprio indirizzo IP all'interno del blocco 172.17.0.0/16. Trova l'indirizzo IP di questo contenitore con
ip
:docker exec -it node_container ip addr show eth0
Puoi testare questa connessione eseguendo il ping di questo indirizzo dall'host Docker.
-
Esegui l'app:
docker exec -it node_container node home/app.js
Se la configurazione è andata a buon fine, il programma dovrebbe visualizzare l'output della console "Hello world" come prima.
Collega due contenitori
In questa sezione, sia l'app che il database verranno eseguiti in contenitori separati. Puoi utilizzare l'immagine postgres ufficiale da Docker Hub e caricarla nel dump SQL creato in precedenza.
Attenzione Non archiviare i dati del database di produzione all'interno di un contenitore Docker. I contenitori devono essere trattati come entità effimere:se un contenitore si arresta in modo imprevisto o viene riavviato, tutti i dati nel database andranno persi.
-
Arresta e rimuovi il contenitore Node.js:
docker stop node_container docker rm node_container
-
Tira il
postgres
immagine:docker pull postgres
-
Assicurati che il tuo
backup.sql
il file si trova nella directory di lavoro corrente, quindi eseguipostgres
immagine:docker run -d -v `pwd`:/backup/ --name pg_container postgres
Il
-v
l'opzione monta la directory di lavoro corrente su/backup/
directory nel nuovo contenitore. -
Il nuovo contenitore avvierà automaticamente il database postgres e creerà l'utente postgres. Entra nel container e carica il dump SQL:
docker exec -it pg_container bash cd backup psql -U postgres -f backup.sql postgres exit
-
Eseguire nuovamente l'immagine del nodo. Questa volta, invece di
--add-host
, usa il--link
opzione per connettere il container a pg_container:docker run -d --name node_container --link=pg_container:database node_image
Questo collegherà il
pg_container
sotto il nome hostdatabase
. -
Apri
/etc/hosts
in node_container per confermare che il collegamento è stato effettuato:docker exec -it node_container cat /etc/hosts
Dovrebbe esserci una riga simile alla seguente:
- File:/ ecc/host
172.17.0.2 database pg_container
Questo mostra che
pg_container
è stato assegnato all'indirizzo IP 172.17.0.2 ed è collegato a questo container tramite il nome hostdatabase
, come previsto. -
Poiché l'app Node.js si aspetta ancora di connettersi a un database PostgreSQL sul
database
host, non sono necessarie ulteriori modifiche. Dovresti essere in grado di eseguire l'app come prima:docker exec -it node_container node home/app.js
Utilizzo di Docker Compose
Usando il --link
o --host
le opzioni ogni volta che avvii i contenitori possono essere ingombranti. Se il tuo server o uno qualsiasi dei contenitori si arresta in modo anomalo, devono essere ricollegati manualmente. Questa non è una situazione ideale per qualsiasi applicazione che richieda una disponibilità costante. Fortunatamente, Docker fornisce Docker Compose per gestire più contenitori e collegarli automaticamente insieme all'avvio. Questa sezione utilizzerà Docker Compose per riprodurre i risultati della sezione precedente.
Nota Per una spiegazione più completa di Docker Compose e come scrivere docker-compose.yml
file di configurazione, consulta la nostra guida completa di Docker Compose.
-
Installa Docker Compose:
sudo curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
-
Nella stessa directory del tuo Dockerfile, crea un
docker-compose.yml
file con il seguente contenuto:- File:docker -compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
version: '3' services: database: image: postgres container_name: pg_container volumes: - pgdata:/var/lib/postgresql/data app: build: . container_name: node_container links: - database environment: - PGPASSWORD=newpassword - PGUSER=postgres - PGDATABASE=nodejs - PGHOST=database - PGPORT=5432 depends_on: - database volumes: pgdata: {}
Quando esegui Docker Compose con questo file, verrà creato il
pg_container
enode_container
dalla sezione precedente. Come prima, il contenitore del database utilizzerà l'immagine PostgreSQL ufficiale, mentre il contenitore dell'app verrà creato dal tuo Dockerfile. Ilinks
la voce ha la stessa funzione di--link
opzione inrun
comando utilizzato in precedenza. -
Docker Compose ti consente anche di impostare i valori dell'ambiente, in modo da poter semplificare l'uso dell'app anziché avere i valori codificati. Modifica
app.js
per rimuovere questi valori:- File:app .js
1 2 3 4 5 6 7 8 9 10 11
const express = require('express') const { Client } = require('pg') const client = new Client() client.connect() client.query('SELECT * FROM hello', (err, res) => { console.log(res.rows[0].message) client.end() })
-
Rimuovi i contenitori precedenti:
docker rm -f node_container pg_container
-
Usa Docker Compose per visualizzare i contenitori:
docker-compose up -d
-
Carica i dati di esempio nel nuovo contenitore:
docker cp backup.sql pg_container:/ docker exec -it pg_container psql -U postgres -f backup.sql postgres
-
Esegui
app.js
dal contenitore dell'app:docker exec -it node_container node home/app.js
L'app dovrebbe funzionare come prima.
Conclusione
Per impostazione predefinita, Docker assegna automaticamente un indirizzo IP a ciascun container e all'host Docker. Puoi connettere manualmente i servizi tra i container utilizzando questi indirizzi (supponendo che il tuo firewall consenta la connessione).
Tuttavia, Docker fornisce anche una serie di comodi wrapper attorno a queste connessioni per aiutarti a velocizzare e semplificare il processo di connessione. Puoi connettere il tuo host Docker a un container con un nome host univoco o collegare direttamente due container. L'uso di Docker Compose può semplificare ulteriormente questo processo consentendo di dichiarare le connessioni in docker-compose.yml
file in modo che vengano stabiliti automaticamente quando vengono richiamati i contenitori.
Ci sono altre opzioni di connessione che non sono state trattate in questa guida. Ad esempio, puoi eseguire un container utilizzando --net="host"
, che condividerà lo stack di rete del contenitore con l'host Docker:localhost
sul contenitore punterà a localhost
sull'host Docker. Puoi anche esporre le porte su ciascun container Docker o configurare la rete bridge predefinita per una maggiore flessibilità. Per una discussione più approfondita di queste opzioni, vedere i collegamenti nella sezione Ulteriori informazioni di seguito.
Maggiori informazioni
Si consiglia di consultare le seguenti risorse per ulteriori informazioni su questo argomento. Sebbene questi siano forniti nella speranza che possano essere utili, tieni presente che non possiamo garantire l'accuratezza o la tempestività dei materiali ospitati esternamente.
- Docker:comprensione della comunicazione dei container
- Contenitori di collegamento
- Contenitori di collegamento