Xarxa
Els contenidors es poden connectar i comunicar-se entre ells o altres serveis mitjançant xarxes.
Introducció
Docker utilitza una interfície virtual que té el nom de docker0 que es va crear quan vas instal.lar docker.
Quan crees un contenidor aquest es connecta a aquesta xarxa:
En aquest cas el contenidor té l’adreça 172.17.0.2 de la xarxa 172.17.0.1/16 que pertany a la interfície virtual docker0.
Si intentes conectar-te amb localhost no pots, però si et connectes directament a la IP del contenidor si que pots:
)
<html><body><h1>It Quan crees un contenidor a aquest se li pot assignar qualsevol IP de la xarxa docker0.
És per aquest motiu que quan arrenquem un servidor web fem un port forward per poder accedir al servidor des de l’adreça localhost amb l’opció -p 80:80:
Ara podem accedir al servidor tant des de l’adreça 127.0.0.1 com l’adreça 172.17.0.2:
<html><body><h1>It
<html><body><h1>It Això és possible perqué docker ha definit una regla a la taula nat de {% link “/linux/netfilter/” %}
|
La regla diu que si un paquet tcp destinat al port 80 va a una interfície que no sigui docker0, aquest serà redirigit a 172.17.0.2:80.
Si elimines el contenidor pots verificar que la regla desapareix:
|
A continuació crearem 3 apaches:
Pots veure les adreçes i ports on estan escoltant els servidors a la taula nat:
|
A més, com tots els contenidors comparteixen la mateixa xarxa es poden comunicar entre ells!
Xarxes predefinides
De manera predeterminada, Docker inclou tres xarxes i cadascuna és proporcionada per un “driver” diferent:
Bridge
La xarxa bridge correspon a la intefície virtual docker0 que hem vist abans.
Host
Enlloc d’executar el contenidor en una xarxa privada pots executar-lo directament com si fos qualsevol altre procés amb l’opció --network host.
D’aquesta manera el contenidor té accés als serveis que s’executen a localhost i a qualsevol altre interfície del host.
Com pots veure a continuació un contenidor no té accés a les intefícies del host, només veu les seves:
Pero si fem servir l’opció --network host té accés a totes les interfícies de la màquina:
També pots executar un servidor apache sense necessitat de fer un “port forward”:
<html><body><h1>It None
També pots executar un contenidor sense que tingui accés a xarxa:
La única interfície que té és localhost:
Pots verificar que el contenidor no es pot connectar a l’exterior:
A diferència d’un contenidor connectat a una xarxa bridgeo host:
)
NodePort
Fins ara no haviem explicat res de la interficie bridge i només et deiem que afegixis l’opció -p 80:80.
Quan crees un contenidor pots configurar diversos “port forward” amb l’opció -p (o --publish), i no es poden canviar més endavant.
L’opció -p necessitat com argument la interfície de l’amfitrió, el port de l’amfitrió, el port de destinació i el protocol de port.
Per exemple, cadascuna d’aquestes opcions reenviarà el port TCP 8080 des de totes les interfícies d’amfitrió al port TCP 8080 del nou contenidor.
-p 0.0.0.0:8080:8080/tcp
-p 8080:8080/tcp
-p 8080:8080El primer argument és la forma completa.
Exemple
En aquest exemple fem un “port forward2 del port 80 de interficie 0.0.0.0 al port 80 de la IP 172.17.0.x.
<html><body><h1>It
<html><body><h1>It Perquè diem a la interfície 172.17.0.x? Perquè el contenidor estarà connectat a la xarxa bridge, però no sabem quina serà la IP que se li assignarà i ens és indiferent.
Si vols saber quina és la IP exacta mira el fitxer /etc/hosts:
|
<html><body><h1>It
Per què aquest exemple no funciona?
) Perquè apache està escoltant al port 80 de la IP 172.17.0.x i no al port 8000.
&&
Per què aquest exemple no funciona?
)
Perquè apache està escoltant al port 80/tcp de la IP 172.17.0.x i no al port 80/udp.
Recordeu:
Perquè aquest exemple si funciona en el port 80, 3000 i 8000 ?
<html><body><h1>It
<html><body><h1>It
<html><body><h1>It Perquè hi ha 3 “port forwards”: 80 → 80, 3000 → 80 i 8000 → 80
I això vol dir que hi ha tres regles a la taula nat de netfilter amb port forward a la IP del contenidor al port 80:
|
Per què aquest exemple funciona en totes les interfícies del host?
<html><body><h1>It
<html><body><h1>It
<html><body><h1>It
<html><body><h1>It Perquè per defecte el “port forward” es fa amb la IP 0.0.0.0, que vol dir totes.
Per què aquest exemple només funciona amb la IP 192.168.123.6 ?
)
<html><body><h1>It
)
) Si mirem la taula nat …
|
Port aleatori
A vegades quan tens molts contenidors funcionant només vols fer un “port forward” des de qualsevol port que estigui disponible.
En aquest cas només has de dir el port destí sobre el qual es farà el “port forward”:
) Podem fer un nmap per veure en quin port està escoltant:
I provar … o mirar la taula nat:
|
Doncs és el port 32768, però si hi ha molts contenidors …
Amb l’ordre docker port puc conèixer en quins ports s’està fent un “port forward” a un contenidor!
Solucionat!
<html><body><h1>It Xarxes definides per l’usuari
Molts contenidors no funcionen sols sinó que depenen d’altres contenidors per funcionar, i la manera de connectar aquests contenidors és mitjançat xarxes virtuals.
Les xarxes definides per l’usuari, encara que facin servir el mateix driver que la xarxa predefinida bridge, tenen més funcions com per exemple la resolució DNS.
Crea una xarxa virtual específica amb el nom xarxa-1:
|
|
L’opció --attachable permet connectar i desconnectar contenidors a la xarxa en qualsevol moment.
Amb l’opció --subnet pots definir la subxarxa.
Crea un contenidor amb name explorer que estigui connectat a la xarxa xarxa-1 i mira les interficies disponibles del contenidor:
Amb l’opció --network hem fet que el contenidor es vinculi a la xarxa xarxa-1 i no a docker0.
Crea una altre xarxa virtual amb el nom xarxa-2:
|
|
Pots veure que:
- Al host ara hi ha dos xarxes virtuals més
- Que la interfície
br-10db898153bestàUP(té un contenidor) i la interfíciebr-8afdb8106b83estàDOWN(no té cap contenidor).
Connecta el contenidor explorer a la xarxa xarxa-2 i verifica que ara té dos interfícies eth:
Una xarxa només té sentit si hi ha més d’un participant.
Com podem saber si hi ha algú més? Utilitzant {% link “/network/nmap/” %}
Entra dins el contenidor explorer i instal.la nmap:
&& Escaneja les xarxes a les que està connectat el contenidor:
|
|
)
)
)
) Pots veure que en les dos xarxes només està el contenidor i el host.
Crea un altre contenidor connecta’t a la xarxa xarxa-2 amb el nom jupyter:
Torna a executar nmap des del contenidor explorer:
|
)
)
) Pots veure que hi ha un nou node amb IP 10.10.42.3 i nom jupyter.xarxa-2.
nmap pot resoldre aquesta IP perquè hi ha un servidor DNS que resolt IPs amb el nom de contenidor.
Verifica que pots resoldre el nom jupyter:
)
DNS
El Sistema de noms de domini (DNS) és un protocol per assignar noms de hosts a adreces IP.
D’aquesta manera un host pot connectar-se a un altre host mitjançant un nom enlloc d’una IP.
hostname
Per defecte docker utilitza el nom del contenidor com a hostname:
Recorda que la xarxa per defecte (bridge) no té resolució DNS:
;; ; Amb l’opció --hostname pots especificar un altre nom alternatiu:
|
|
bye és un nom alternatiu a hello !
Servidor DNS
Per defecte, el contenidor fa servir el servei DNS del host:
Però si vols pots crear un contenidor configurat amb un altre servidor dns També pots especificar un o més servidors DNS per utilitzar.
Per exemple, el servidor DNS 1.1.1.1 de Cloudflare:
Mira com és per defecte el fitxer /etc/resolv.conf d’un contenidor:
Mira com és el fitxer /etc/resolv.conf d’un contenidor amb l’opció dns:
Amb l’opció -dns modifiques el fitxer /etc/resolv.conf !
DNS Search
També pots utilitzar l’opció --dns-search per especificar un domini de cerca DNS.
Activitats
Postgres
PostgreSQL és una de les bases de dades relacionals més utilitzades.
Crea un contenidor postgres:
Executa un terminal interactiu en el contenidor postgres i crea una taula client amb dos entrades:
);
);
);
;
()
Crea un contenidor postgres en la mateixa xarxa:
Amb el flag -h postgres el client es conectarà al servidor postgres que estigui en la IP que resolgui el DNS pel nom postgres:
()
Ara enlloc de fer servir la resolució DNS utilitzarem directament la IP:
|
()
Pots verificar que és el contenidor que hem creat abans perquè té una taula client amb els registres ‘Mary’ i ‘Mike’.
Això és possible perquè els dos contenidors estan en la mateixa xarxa!
Crea un contenidor postgres en la xarxa-2 i verifica que no et pots conectar al contenidor postgres ni per nom ni per IP:
Wordpress
Si vols més informació ves a {% link “/web/app/wordpress/” %}
Hi ha moltes aplicacions que necessiten un base de dades, per exemple Wordpress:
Crea un contenidor mariadb pel wordpress:
Crea un contenidor Wordpress:
Crea una base de dades pel Wordpress:
;
;
;
;
Ja pots obrir un navegador al Wordpress:

Amb el contenidor explorer i fes un nmap de les xarxes:
|
Pots veure que la base de dades wordpress s’ha omplert de taules.
;
;
;HAProxy
HAProxy és un balancejador de càrrega d’alta disponibilitat (i proxy invers) per TCP i aplicacions HTTP.
Crea un volum amb el nom apache ( a {% link “/linux/docker/storage/” %} ja parlarem de volums):
Crea una xarxa amb el nom apache :
Crea tres contenidor apache a la xarxa apache amb el volum apache montat a /usr/local/apache2/htdocs/:
Pots veure que els tres servidor apache són accessibles des de la xarxa 10.10.51.0/24, però només des d’aquesta xarxa:
Entra en el contenidor apache-1 i modifica el contingut del fitxer index.html:
Com que tots els apaches comparteixen el mateix volum, tenen el mateix fitxer index.html:
&&
Crea un fitxer de configuració haproxy.cfg:
Arrenca un contenidor haproxy en la xarxa apache amb aquest fitxer i un “port forward” 9000:80:
Verifica que haproxy funciona amb tres, dos, un i cap apache actius.
) Quan el proxy no té cap apache que li respongui (estan tots parats) retorna una resposta buida: Empty reply from server.
Arrenca un apache i verifica que el proxy torna a funcionar (al cap d’uns segons)