Outils pour utilisateurs

Outils du site


sysadmin:docker:configuration_reseau

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
sysadmin:docker:configuration_reseau [2021/08/23 08:27] – créée yoannsysadmin:docker:configuration_reseau [2022/12/12 22:03] (Version actuelle) – Ajout d'un lien référence yoann
Ligne 1: Ligne 1:
-{{tag>sysadmin netadmin docker network réseau todo}}+{{tag>sysadmin netadmin docker network réseau}}
  
 ====== Docker: Configuration réseau des conteneurs ====== ====== Docker: Configuration réseau des conteneurs ======
  
-===== Domaine de recherche =====+Pour des généralités concernant la conception et la gestion des réseaux avec Docker voir la note [[sysadmin:docker:concepts_et_philosophie_gestion_reseau]].
  
-Il est possible de spécifier un ou plusieurs domaines de recherchers pour les noms de machine non pleinement qualifiés. 
  
-En ligne de commande via les +Initialement Docker possède 3 réseaux. Les réseaux existants peuvent être listés via la commande **''docker network ls''**. Succinctement on peut dire:
  
-Via le docker-compose+^ bridge  | Réseau utilisé par défaut pour les conteneurs. 
 +^ host    | Le conteneur utilise la même interface que la machine hôte. A réserver à des usages spécifiques.| 
 +^ none    | Pas de connexion réseau |
  
 +===== Réseau par défaut =====
 +
 +Si on crée un conteneur sans spécifier de réseau c'est le réseau **bridge** qui est utilisé. Pour le vérifier:
 +
 +<code bash>
 +# création d'un conteneur sans définition concernant le réseau
 +docker container run --name busybox --rm -it busybox:latest /bin/sh
 +
 +# depuis le shell du conteneur, on affiche les interfaces et la passerelle
 +ip a show
 +
 +1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
 +    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 +    inet 127.0.0.1/8 scope host lo
 +       valid_lft forever preferred_lft forever
 +17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
 +    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
 +    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
 +       valid_lft forever preferred_lft forever
 +
 +ip route show
 +
 +default via 172.17.0.1 dev eth0 
 +172.17.0.0/16 dev eth0 scope link  src 172.17.0.2 
 +</code>
 +
 +Le conteneur utilise le réseau 172.17.0.0/16, il a l'adresse 172.17.0.2 et contacte la passerelle 172.17.0.1 pour joindre tout autre réseau. Si on affiche les interfaces de la machine hôte exécutant Docker Engine, on peut voir une interface nommée **docker0**:
 +
 +<code bash>
 +# Liste des interfaces de la machine hôte
 +ip addr show
 +. . .
 +6: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
 +    link/ether 02:42:f5:c5:d5:9d brd ff:ff:ff:ff:ff:ff
 +    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
 +       valid_lft forever preferred_lft forever
 +    inet6 fe80::42:f5ff:fec5:d59d/64 scope link 
 +       valid_lft forever preferred_lft forever
 +
 +. . .
 +</code>
 +
 +Ici on voit que l'interface **docker0** à l'adresse 172.17.0.1, c'est donc la **passerelle du réseau par défaut bridge**.
 +
 +Le conteneur se voit attribuer une adresse IP pour chaque réseau auquel il est connecté. Le daemon Docker agit à la manière d'un serveur DHCP et fournit une IP dans le pool réservé au réseau. Chaque réseau à son propre masque et sa passerelle par défaut.
 +
 +===== Spécifier le réseau du conteneur =====
 +
 +On peut spécifier le réseau auquel connecter le conteneur via l'argument **%%--net%%** ou **%%--network%%**:
 +
 +<code bash>
 +# Ici on isole le conteneur en l'associant au réseau none
 +docker container run --rm -it --name conteneur_test --net=none busybox:latest /bin/sh
 +
 +# Equivalent
 +docker container run --rm -it --name conteneur_test --network none busybox:latest /bin/sh
 +/ # ip a show
 +1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
 +    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 +    inet 127.0.0.1/8 scope host lo
 +       valid_lft forever preferred_lft forever
 +</code>
 +
 +
 +Lors de sa création, le conteneur ne peut être connecté qu'à un seul réseau. Celui-ci peut être définit sur la ligne de commande via l'option **%%--network%%**. On peut également spécifier une adresse IP via les options **%%--ip%%** ou **%%--ip6%%**. Si rien n'est spécifié, un réseau dédié est créé pour le conteneur.
 +
 +<code bash>
 +# Création d'un conteneur en mode interactif
 +docker run --interactive --tty --name network_test busybox:latest /bin/sh
 +
 +# Shell dans le conteneur
 +# On affiche IP de l'interface réseau du conteneur créée par défaut
 +ip addr show
 +...
 +24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
 +    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
 +    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
 +       valid_lft forever preferred_lft forever
 +
 +# on quitte le shell, l’exécution du conteneur est stoppée
 +exit
 +</code>
 +
 +
 +Afficher les paramètres réseau actuels du conteneur ''network_test'':
 +<code bash>
 +docker container inspect --format "{{json .NetworkSettings}}" network_test | jq
 +</code>
 +
 +On redémarre le conteneur et on le connecte à un réseau docker supplémentaire existant sur l’hôte. Ici pour l'exemple vnet-monitoring
 +
 +
 +<code bash>
 +# Démarrer le conteneur qui rejoint son réseau par défaut
 +docker container start network_test
 +
 +# Connecter le conteneur sur un autre réseau, ici vnet-monitoring
 +docker network connect vnet-monitoring network_test
 +</code>
 +
 +On ouvre un shell dans le conteneur pour afficher les paramètres réseau
 +<code bash>
 +docker container exec --interactive network_test /bin/sh
 +
 +ip a
 +...
 +26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
 +    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
 +    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
 +       valid_lft forever preferred_lft forever
 +28: eth1@if29: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
 +    link/ether 02:42:ac:18:00:04 brd ff:ff:ff:ff:ff:ff
 +    inet 172.24.0.4/16 brd 172.24.255.255 scope global eth1
 +       valid_lft forever preferred_lft forever
 +
 +</code>
 +
 +On constate bien qu'une nouvelle interface connecte le conteneur au réseau 172.24.0.0/16
 +
 +===== Accès au conteneur depuis l'extérieur =====
 +
 +Pour accèder au conteneur (et à ses services) depuis l'extérieur du réseau dans lequel il est confiné, Docker permet de crééer des translations par port ou **PAT**((**P**ort **A**ddress **T**ranslation)).
 +On associe des ports libres de l'hote aux ports à l'écoute des conteneurs via le paramètre **%%--publish%%**:
 +
 +<code bash>
 +# Associe a un port libre de l'hote le port 80 du conteneur
 +docker run --rm -d --name nginx --publish=80 nginx:alpine
 +
 +# Associe le port 8080 de l'hote au port 80 du conteneur
 +docker run --rm -d --name nginx --publish=8080:80 nginx:alpine
 +</code>
 +
 +===== Liaison entre conteneurs =====
 +
 +Pour faire communiquer des conteneurs en interne, on peut s'appuyer sur les liaisons en utilisant l'option **%%--link%%**.
 +
 +Création d'un conteneur container_server en mode interactif
 +<code bash>
 +docker container run -it --rm --name container_server -h server01 busybox:latest /bin/sh
 +
 +# Depuis le conteneur, on affiche le nom de la machine
 +hostname
 +
 +server01
 +</code>
 +
 +On souhaite pouvoir joindre via le réseau interne de Docker le conteneur "container_server". Pour cela lors de la création du conteneur client on utilise l'option **%%--link conteneur_a_joindre:alias%%**:
 +
 +<code bash>
 +docker container run -it --rm --name container_client -h client01 --link container_server:server busybox:latest /bin/sh 
 +
 +# Depuis le shell du conteneur container_client
 +cat /etc/hosts 
 +
 +127.0.0.1       localhost
 +::1     localhost ip6-localhost ip6-loopback
 +fe00::0 ip6-localnet
 +ff00::0 ip6-mcastprefix
 +ff02::1 ip6-allnodes
 +ff02::2 ip6-allrouters
 +172.17.0.2      server server01 container_server
 +172.17.0.3      client01
 +</code>
 +
 +Le fichier **/etc/hosts** du client est alors complété avec l'IP du conteneur serveur, et les noms associés.
 +
 +<note>
 +Selon la façon dont est construite l'image du conteneur auquel on s'est lié (notamment via la directive EXPOSE du dockerfile) on peut également retrouver des informations concernant l'adresse du conteneur, les ports et les protocoles exposés dans les variables environnement.
 +</note>
 +
 +===== Nommage des interfaces =====
 +
 +Lorsque qu'un nouveau réseau est créé via la commande **docker network** ou via **docker-compose**, un nom générique est attribué pour la nouvelle interface virtuelle créée sur le système. Ce nom est en général de la forme br-xxxxxxxxxxxx le suffixe correspondant au hash du réseau.
 +
 +<code bash>
 +# liste les réseau existants
 +docker network list
 +NETWORK ID     NAME            DRIVER    SCOPE
 +...
 +44f93d295888   webadmin_vnet   bridge    local
 +
 +# liste les interfaces réseaux:
 +ip link show
 +1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
 +    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 +...
 +25: br-44f93d295888: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
 +    link/ether 02:42:00:07:2e:f8 brd ff:ff:ff:ff:ff:ff
 +</code>
 +
 +Dans exemple ci-dessus, le réseau docker d'identifiant 44f93d295888 correspond à l'interface br-44f93d295888 du système.
 +
 +Pour plus de clarté, ou si on souhaite fixer le nom de l'interface (utile pour définir des règles iptables) il est possible de spécifier le nom de l'interface.
 +
 +Depuis la ligne de commande:
 +
 +<code bash>
 +docker network create --opt com.docker.network.bridge.name=br_test test-net
 +</code>
 +
 +Depuis un fichier docker-compose:
 +<file YAML>
 +networks:
 +  test-net:
 +    driver: bridge
 +    ipam:
 +     driver: default
 +     config:
 +       - subnet: 172.100.0.0/16
 +    driver_opts:
 +      com.docker.network.bridge.name: br_test
 +</file>
 +
 +===== Définir l'adresse IP du conteneur =====
 +
 +Il est possible d'attribuer une adresse IP statique au conteneur:
 +
 +<file YAML>
 +version: "3.3"
 +
 +networks:
 +  vnet:
 +    driver: bridge
 +    ipam:
 +      config:
 +        - subnet: 172.24.0.0/16
 +          gateway: 172.24.0.1
 +
 +services:
 +  srv_1:
 +    ...
 +    networks:
 +      vnet:
 +        ipv4_address: 172.24.0.10
 +</file>
 +
 +===== Création d'alias =====
 +
 +Les alias permettent de définir des noms d’hôtes alternatifs via lesquels un service pourra être atteint au sein d'un réseau.
 +
 +<file YAML>
 +version: "3.3"
 +
 +networks:
 +  vnet-monitoring:
 +    external:
 +      name: vnet-monitoring
 +
 +services:
 +  node-exporter:
 +    image: prom/node-exporter:v1.2.2   
 +    container_name: node-exporter
 +    restart: unless-stopped
 +    environment: {}
 +    networks:
 +      vnet-monitoring:
 +        aliases:
 +          - localnode
 +</file>
 +
 +Dans l'exemple ci-dessus, le service ''node-exporter'' est inséré dans le réseau externe ''vnet-monitoring''. Au sein de se réseau, on pourra communiquer avec le service node-exporter en le désignant indifféremment ''node-exporter'' ou ''localnode''.
 +
 +
 +<code bash>
 +$ docker container run --rm --interactive --tty --network vnet-monitoring busybox:latest 
 +/ # ping node-exporter
 +PING node-exporter (172.24.0.4): 56 data bytes
 +64 bytes from 172.24.0.4: seq=0 ttl=64 time=0.165 ms
 +64 bytes from 172.24.0.4: seq=1 ttl=64 time=0.196 ms
 +64 bytes from 172.24.0.4: seq=2 ttl=64 time=0.178 ms
 +^C
 +--- node-exporter ping statistics ---
 +3 packets transmitted, 3 packets received, 0% packet loss
 +round-trip min/avg/max = 0.165/0.179/0.196 ms
 +
 +/ # ping localnode
 +PING localnode (172.24.0.4): 56 data bytes
 +64 bytes from 172.24.0.4: seq=0 ttl=64 time=0.223 ms
 +64 bytes from 172.24.0.4: seq=1 ttl=64 time=0.201 ms
 +</code>
 +
 +===== Peuplement du fichier /etc/host =====
 +
 +:TODO: :TODO_DOCUPDATE:
 +
 +https://runebook.dev/fr/docs/docker/engine/reference/run/index
 +
 +===== Résolution de nom =====
 +
 +Les conteneurs qui utilisent la connexion réseau par défaut (default bridge)  héritent des paramètres définis dans le fichier **/etc/resolv.conf** de la machine hôte (copie du fichier).
 +
 +<code bash>
 +# Affiche les paramètres de résolution de l’hôte
 +cat /etc/resolv.conf 
 +search phobos.lan
 +nameserver 192.168.33.254
 +
 +# Création d'un conteneur temporaire en mode interactif
 +# avec une connexion par défaut
 +docker container run --rm -it --name test_dns1 busybox:1.34-glibc /bin/sh
 +
 +# Depuis le shell dans le conteneur, on affiche les paramètres DNS
 +cat /etc/resolv.conf 
 +search phobos.lan
 +nameserver 192.168.33.254
 +</code>
 +
 +Dans l'exemple ci-dessus on constate bien que le serveur DNS dans le conteneur est identique à celui de l’hôte.
 +
 +Petite particularité pour les hôtes utilisant **systemd-resolved** (cache DNS local), c'est le fichier ''/run/systemd/resolve/resolv.conf'' qui indique quelle adresse les services locaux doivent utiliser pour la résolution de nom. Le Docker Engine affecte alors cette adresse au conteneur.
 +
 +Pour définir quels serveurs DNS le conteneur doit utiliser, définir une ou plusieurs fois l'option **%%--dns%%**. Il est également possible de spécifier un ou plusieurs domaines de recherche pour les noms de machine non pleinement qualifiés via l'option **%%--dns-search%%**.
 +
 +<code bash>
 +# crée le conteneur en mode interactif
 +docker container run -it --rm --name dns_test --dns="172.24.0.53" --dns-search="private.lan" busybox:1.34-glibc /bin/sh
 +
 +# Affiche la configuration dns du conteneur
 +cat /etc/resolv.conf 
 +search private.lan
 +nameserver 172.24.0.53
 +</code>
 +
 +
 +Via le docker-compose en valeur simple
 +<file YAML>
 +
 +</file>
 +
 +Via le docker-compose en listes
 +<file YAML>
 +</file>
 +
 +En revanche, les conteneurs connectés à des réseaux personnalisés utilisent systématiquement le serveur DNS intégré à Docker (adresse 127.0.0.11). **Celui-ci est configurable via la ligne de commande ou le docker-compose mais l'adresse visible depuis le conteneur est toujours 127.0.0.11**.
 +
 +
 +
 +sources:
 +  * https://transang.me/dns-server-in-docker-container/
 +  * https://docs.docker.com/config/containers/container-networking/#dns-services
  
 ===== Références ===== ===== Références =====
  
   * https://docs.docker.com/config/containers/container-networking/   * https://docs.docker.com/config/containers/container-networking/
 +  * https://stackoverflow.com/questions/43579740/in-docker-compose-how-to-create-an-alias-link-to-localhost#43579846
 +  * https://docs.docker.com/compose/compose-file/compose-file-v3/#aliases
 +  * https://stackoverflow.com/questions/39493490/provide-static-ip-to-docker-containers-via-docker-compose
 +  * https://linuxconfig.org/basic-example-on-how-to-link-docker-containers
 +  * https://runebook.dev/fr/docs/docker/engine/reference/run/index
 +  * https://kerneltalks.com/networking/how-docker-container-dns-works/
  
sysadmin/docker/configuration_reseau.1629707244.txt.gz · Dernière modification : 2021/08/23 08:27 de yoann