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
postgrespassword utente:sudo passwd postgres -
Imposta una password per
postgresutente 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
postgresUtente 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.confin un editor di testo. Decommenta illisten_addressesriga 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
postgresqlservizio: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.jse aggiungi il seguente contenuto:- File:app .js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16const { 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
pgModulo 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 ilpostgrespassword utente del database che hai impostato nella sezione precedente.Nota Il
pgmodulo 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
pgmodulo:npm install pg -
Prova l'app:
node app.jsSe 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 7FROM 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.jsper consentire all'app di connettersi aldatabasehost invece dilocalhost:- File:app /app.js
1 2 3 4 5 6 7const 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
docker0interfaccia di rete. Usaifconfigoipper visualizzare questa interfaccia:ifconfig docker0L'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.confin un editor di testo e aggiungi la seguente riga:- File:/ etc/postgresql/9.5/main/pg_hba.conf
1host 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_imageIl
--add-hostl'opzione definisce undatabasehost, che punta all'indirizzo IP dell'host Docker. Dichiarazione deldatabasehost in fase di esecuzione, anziché codificare l'indirizzo IP nell'app, aiuta a mantenere il contenitore riutilizzabile. -
Dall'interno del contenitore, usa
pingper testare la connessione aldatabaseospite: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 eth0Puoi 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
postgresimmagine:docker pull postgres -
Assicurati che il tuo
backup.sqlil file si trova nella directory di lavoro corrente, quindi eseguipostgresimmagine:docker run -d -v `pwd`:/backup/ --name pg_container postgresIl
-vl'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--linkopzione per connettere il container a pg_container:docker run -d --name node_container --link=pg_container:database node_imageQuesto collegherà il
pg_containersotto il nome hostdatabase. -
Apri
/etc/hostsin node_container per confermare che il collegamento è stato effettuato:docker exec -it node_container cat /etc/hostsDovrebbe 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
databasehost, 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.ymlfile 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 25version: '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_containerenode_containerdalla sezione precedente. Come prima, il contenitore del database utilizzerà l'immagine PostgreSQL ufficiale, mentre il contenitore dell'app verrà creato dal tuo Dockerfile. Ilinksla voce ha la stessa funzione di--linkopzione inruncomando 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.jsper rimuovere questi valori:- File:app .js
1 2 3 4 5 6 7 8 9 10 11const 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.jsdal 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