Comprendre le réseau sous Docker 1/2 : le Bridge

Ludovic QUENEC'HDU
Ludovic QUENEC'HDU 5 commentaires 9e lecture en min

Ceci est le premier article sur la gestion du réseau sous Docker. Dans ce post, nous allons  découvrir  ensemble comment sont connectés nos conteneurs sur le réseau, créer des réseaux et utiliser ces réseaux pour nos conteneurs.

1- Le réseau ponte ou le Bridge docker

Lors de l’installation de Docker, trois réseaux sont créés automatiquement. On peut voir ces réseaux avec la commande docker network ls. Un réseau de type bridge est créé :

				
					#docker network ls NETWORK ID          NAME                DRIVER              SCOPE 32cd2d55155f        bridge              bridge              local b7fe5d1b69a7        host                host                local de5ae709fdcd        none
				
			

Le réseau Bridge est présent sur tous les hôtes Docker. Lors de la création d’un conteneur, si l’on ne spécifie pas un réseau particulier, les conteneurs sont connectés au Bridge docker0.

La commande ifconfig ou ip a fournit les informations sur le réseau ponté (bridge).

				
					docker0 Link encap:Ethernet HWaddr 02:42:47:bc:3a:eb
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:17 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1100 (1.1 KB) TX bytes:648 (648.0 B)
				
			

La commande docker network inspect bridge, retourne les informations concernant ce réseau :

				
					#docker network inspect bridge

[ 

  { 
      "Name": "bridge", 
       "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
      "Scope": "local",
      "Driver": "bridge",
      "IPAM": {
      "Driver": "default", 
      "Config": [
{
         "Subnet": "172.17.0.1 /16",
         "Gateway": "172.17.0.1"
      }
   ] 
},
"Containers": {},
"Options": {
    "com.docker.network.bridge.default_bridge": "true",
     "com.docker.network.bridge.enable_icc": "true",
     "com.docker.network.bridge.enable_ip_masquerade": "true",
     "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
     "com.docker.network.bridge.name": "docker0",
     "com.docker.network.driver.mtu": "9001"
},
"Labels": {}
   } 
]
				
			

Créons deux containers avec l’image alpine.

				
					#docker run -itd --name=container1 alpine
3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c
#docker run -itd --name=container2 alpine
94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c
				
			

Et visualisons les informations du réseau avec docker network inspect :

				
					 #docker network inspect bridge 
 {[
  
    {
        "Name": "bridge",
         "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
         "Scope": "local",
         "Driver": "bridge",
         "IPAM": { 
                  "Driver": "default",
                  "Config": [
                     {
                      "Subnet": "172.17.0.1/16",
                      "Gateway": "172.17.0.1"
                      } 
            ] 
    },
    "Containers": {
        "3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": {
            "EndpointID":
"647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1", 
         "MacAddress": "02:42:ac:11:00:02",
        "IPv4Address": "172.17.0.2/16",
        "IPv6Address": "" 
        }
    },
    "Options": { 
         "com.docker.network.bridge.default_bridge": "true",
         "com.docker.network.bridge.enable_icc": "true",
         "com.docker.network.bridge.enable_ip_masquerade": "true",
         "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
         "com.docker.network.bridge.name": "docker0",
         "com.docker.network.driver.mtu": "9001"
         },
         "Labels": {}
    } 
]
         
				
			

Les conteneurs sont connectés au Bridge par défaut docker0 et peuvent communiquer entre eux par adresse IP, les conteneurs se trouvent alors, sur le même réseau.

Docker ne prend pas en charge la découverte automatique du service sur le réseau Bridge par défaut. Afin que les conteneurs puissent résoudre les adresses IP par les noms d’hôte des conteneurs on crée des réseaux définis par l’utilisateur.

On peut aussi lier deux conteneurs à l’aide de l’option Legacy docker run –link, mais cela n’est pas recommandé.

2- Réseaux définis par l'utilisateur

Il est recommandé d’utiliser des réseaux Bridgés définis par l’utilisateur pour contrôler quels conteneurs peuvent communiquer entre eux, et ansi permettre la résolution DNS des noms d’hôtes des conteneurs avec les adresses IP.

Docker fournit des pilotes  pour créer ces réseaux. Réseau Bridgé, réseau overlay (Multihost) ou un réseau MACVLAN (Overlay et MacVlan seront vu dans de prochains articles). On peut également créer des plugins réseau ou utiliser un réseau distant. La libraire réseau de Docker , libnetwork (un article sera également consacré a la libnetwork prochainement) peut agir comme un proxy pour des plugins distant, remote driver.

Le réseau ponté ou Bridgé est le réseau par défaut lors de la création de nouveaux réseaux.

On peut  créer autant de réseaux que l’on souhaite et on peut connecter un conteneur à zéro ou plus de ces réseaux à tout moment. On peut également, connecter et déconnecter des conteneurs en cours d’exécution des réseaux sans redémarrer ces deniers.

Réseaux Bridgés

Un réseau Bridgé est le type de réseau le plus utilisé dans Docker. Les réseaux Bridgés créés par les utilisateurs sont semblables au réseau bridge par défaut créé à l’installation de Docker Docker0. Cependant de nouvelles fonctionnalités sont ajoutées, la gestion du DNS par exemple. Lors de la création de nouveau réseau, une nouvelle interface est créée. Cette interface est pontée :

				
					 brctl show
 br-2c601356b5d5        8000.0242b41afdcb    no        vetha2743d6 docker0
 8000.0242fbdce780    no        veth46fbe31
				
			

Création d'un réseau Bridge Blue

				
					#docker network create --driver bridge blue
1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b
 #docker network inspect blue
 [
     { 
        "Name": "blue",
        "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
         "Scope": "local",
         "Driver": "bridge", "IPAM": { "Driver": "default",
         "Config": [
             { 
             
               "Subnet": "172.18.0.0/16",
               "Gateway": "172.18.0.1/16"
               } 
        ] 
   },
   "Containers": {},
   "Options": {},
   "Labels": {}
   } 
]


 #docker network ls
 NETWORK ID              NAME              DRIVER
 9f904ee27bf5            none               null
 cf03ee007fb4            host               host
 7fca4eb8c647            bridge             bridge
 c5ee82f76de3            blue               bridge 
				
			

Connexion d’un container au réseau blue

				
					#docker run --network blue -itd --name blue1 alpine
8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c
 #docker network inspect blue
[
    { 
    
      "Name": "blue", 
      "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
      "Scope": "local", "Driver": "bridge", "IPAM": {
            "Driver": "default",
            "Config": [
                 {}
            ] 
    },
    "Containers":{
        "8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c": {
        "EndpointID": "93b2db4a9b9a997beb912d28bcfc117f7b0eb924ff91d48cfa251d473e6a9b08",
        "MacAddress": "02:42:ac:15:00:02",
        "IPv4Address": "172.18.0.2/16",
        "IPv6Address": ""
      }
  },
  "Options": {},
  "Labels": {}
 } 
]
				
			

Connexion d’un container au réseau blue

 
				
					 #docker run -itd --name blue2 alpine
8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c

 #docker network connect blue blue2

#docker network inspect blue
[
    {
        "Name": "blue",
        "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {}
            ]
        },
        "Containers": {
            "8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c": {
                "EndpointID": "93b2db4a9b9a997beb912d28bcfc117f7b0eb924ff91d48cfa251d473e6a9b08",
                "MacAddress": "02:42:ac:15:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
				
			

Serveur DNS intégré

Docker daemon exécute un serveur DNS intégré qui fournit une résolution de noms aux conteneurs connectés au réseau créé par les utilisateurs, de sorte que ces conteneurs peuvent résoudre les noms de d’hôtes en adresses IP.

Si le serveur DNS intégré est incapable de résoudre la demande, il sera transmis à tous les serveurs DNS externes configurés pour le conteneur. Pour faciliter cela lorsque le conteneur est créé, seul le serveur DNS intégré 127.0.0.11 est renseigné dans le fichier resolv.conf du conteneur.

Testons le serveur DNS intégré :

				
					# docker network create --driver bridge blue
1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b


# docker network inspect blue



[


     { 
     
     
         "Name": "blue",
         "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
         "Scope": "local",
         "Driver": "bridge",
         "IPAM": {
              "Driver": "default",
              "Config": [
              {
                  "Subnet": "172.18.0.0/16", 
                  "Gateway": "172.18.0.1/16"
                  
                  
             } 
      ]
      
      
    },
    
    "Containers": {},
    "Options": {},
    "Labels": {}
    } 
] 

# docker run -it --name blue1 --network blue debian /bin/bash 


# docker run -it --name blue2 --network blue debian /bin/bash 


# docker network inspect blue
[ 
   {
   
   
         "Name": "blue",
         "Id": "2c601356b5d51f3044518bca70c5bc016b2e0a0ccb28475a098185d831c4f27c",
         "Created": "2017-06-07T12:50:24.911280255+02:00",
         "Scope": "local",
         "Driver": "bridge",
         "EnableIPv6": false,
         "IPAM": {
                "Driver": "default",
                "Options": {},
                "Config": [
                
                {
                
                "Subnet": "172.18.0.0/16",                     "Gateway": "172.18.0.1"                 
               }            
        ]        
    },
    "Internal": false,
    "Attachable": false,
    "Containers": {
        "1d105c8c8ab5e84c5cc0e7fac6c57946acc3501c2e9ac202d4a1709a3ab6bd26": {
        
            "Name": "blue1",
            "EndpointID":
"47d0c1a4041b76123ccfa16a94a2a4211b56c1255c52d670091b8dedcf15241c",
            "MacAddress": "02:42:ac:12:00:02",
            "IPv4Address": "172.18.0.2/16",
            "IPv6Address": ""
            
        },
        "feb6d086c7813c621218bed5bda2436cc039c7e30f88e04b39ec669bd95f530c": {
               "Name": "blue2",
               "EndpointID":
"cf2c8d36398b0b73920c522efaa3f4c22aa81e02053d882998b3d9d271fe4f11",
               "MacAddress": "02:42:ac:12:00:03",
               "IPv4Address": "172.18.0.3/16",
               "IPv6Address": ""
            }         
        },
        "Options": {},
         "Labels": {}
     }
     
 ] 
 
 # docker attach blue2
 root@1d105c8c8ab5:/#
 root@feb6d086c781:/# apt-get install dnsutils
 
 
 root@feb6d086c781:/# dig
 ; <<>> DiG 9.9.5-9+deb8u11-Debian <<>> 
 ;; global options: +cmd
 ...... 
 .            119855    IN    NS    k.root-servers.net. 
 .            119855    IN    NS    l.root-servers.net.
 .            119855    IN    NS    m.root-servers.net. 
 
 ;; Query time: 64 msec
 ;; SERVER: 127.0.0.11#53(127.0.0.11) 
 ;; WHEN: Thu Jun 08 08:02:44 UTC 2017
 ;; MSG SIZE  rcvd: 239 
 
 
 
 dig blue1
 
 
 
 ; <<>> DiG 9.9.5-9+deb8u11-Debian <<>> blue1
 ;; global options: +cmd
 ;; Got answer:
 ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63460 
 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
 ;; QUESTION SECTION:
 ;blue1.                IN    A 
 ;; ANSWER SECTION:
 blue1.            600    IN    A    172.18.0.2
 
 
 ;; Query time: 0 msec
 ;; SERVER: 127.0.0.11#53(127.0.0.11)
 ;; WHEN: Thu Jun 08 08:03:21 UTC 2017 ;; MSG SIZE  rcvd: 44
 
 
 root@feb6d086c781:/# cat /etc/resolv.conf 
 nameserver 127.0.0.11 
 options ndots:0
				
			
				
					#docker network create --driver bridge blue
1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b 
#docker network inspect blue 
 
 
 [ 
 
    {
    
       "Name": "blue",
       "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
       "Scope": "local",
       "Driver": "bridge", "IPAM": { 
              "Driver": "default",
              "Config": [
                 {
                      "Subnet": "172.18.0.0/16",
                     "Gateway": "172.18.0.1/16" 
               }
        ] 
    },
    "Containers": {},
    "Options": {},
    "Labels": {} 
   } 
] 
 #docker run -it --name blue1 --network blue debian /bin/bash 
 
 #docker run -it --name blue2 --network blue debian /bin/bash
  
 #docker network inspect blue
   [     
        {        
           "Name": "blue",
           "Id": "2c601356b5d51f3044518bca70c5bc016b2e0a0ccb28475a098185d831c4f27c",
           "Created": "2017-06-07T12:50:24.911280255+02:00",
           "Scope": "local",
           "Driver": "bridge",
           "EnableIPv6": false,
           "IPAM": {
               "Driver": "default",
               "Options": {},
               "Config": [
                   {
                      "Subnet": "172.18.0.0/16",
                     "Gateway": "172.18.0.1"
                  }
            ] 
            
       },
       "Internal": false,
       "Attachable": false,
       "Containers": {
          "1d105c8c8ab5e84c5cc0e7fac6c57946acc3501c2e9ac202d4a1709a3ab6bd26": {
                 "Name": "blue1",
                 "EndpointID": "47d0c1a4041b76123ccfa16a94a2a4211b56c1255c52d670091b8dedcf15241c",
                 "MacAddress": "02:42:ac:12:00:02",
                 "IPv4Address": "172.18.0.2/16",
                 "IPv6Address": ""
            },
            "feb6d086c7813c621218bed5bda2436cc039c7e30f88e04b39ec669bd95f530c": {
                 "Name": "blue2",
                 "EndpointID":
"cf2c8d36398b0b73920c522efaa3f4c22aa81e02053d882998b3d9d271fe4f11",
               "MacAddress": "02:42:ac:12:00:03",
               "IPv4Address": "172.18.0.3/16",
               "IPv6Address": "" 
             }
        },
        "Options": {},
        "Labels": {}
    }
]

 #docker attach blue2
 root@1d105c8c8ab5:/#
 root@feb6d086c781:/# apt-get install dnsutils
 
 
 root@feb6d086c781:/# dig 
 
 
 ; <<>> DiG 9.9.5-9+deb8u11-Debian <<>>
 ;; global options: +cmd
 ......
 .               119855    IN    NS    k.root-servers.net. 
 .            119855    IN     NS    l.root-servers.net
 . .            119855    IN    NS    m.root-servers.net.
 ;; Query time: 64 msec
 ;; SERVER: 127.0.0.11#53(127.0.0.11)
 ;; WHEN: Thu Jun 08 08:02:44 UTC 2017
 ;; MSG SIZE  rcvd: 239
 
 
 
 
 
 dig blue1
 
 
 ; <<>> DiG 9.9.5-9+deb8u11-Debian <<>> blue1
 ;; global options: +cmd 
 ;; Got answer:
 ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63460 
 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
 
 
 ;; QUESTION SECTION:
 ;blue1.                IN    A 
 
 ;; ANSWER SECTION:
 blue1.            600    IN    A    172.18.0.2
 ;; Query time: 0 msec
 ;; SERVER: 127.0.0.11#53(127.0.0.11)
 ;; WHEN: Thu Jun 08 08:03:21 UTC 2017
 ;; MSG SIZE  rcvd: 44
 
 
 root@feb6d086c781:/# cat /etc/resolv.conf
 
 nameserver 127.0.0.11
 
 options ndots:0
				
			

Nos conteneurs sont maintenant connectés au réseau blue et peuvent discuter via les nom d’hôtes. Mais comment accède t’on à ces derniers à partir d’un réseau externe. Le réseau blue est un réseau privé.

Pour plus de maîtrise de Docker, vous pouvez suivre la formation Docker suivante sur Alphorm :

On voit tout cela dans le prochain article 🙂

En Résumé :

  1. Réseau Bridge par Défaut : Explication du réseau Bridge créé automatiquement avec Docker.

  2. Avantages des Réseaux Personnalisés : Importance des réseaux bridgés personnalisés pour un meilleur contrôle.

  3. Création de Réseaux : Procédure pour créer un réseau Bridge personnalisé.

  4. Connexion des Conteneurs : Comment connecter des conteneurs à un réseau personnalisé.

  5. Serveur DNS de Docker : Fonctionnement du serveur DNS intégré dans les réseaux Docker.

Partager cet article
Par Ludovic QUENEC'HDU Expert en Virtualisation et Sécurité Informatique au Service de Grands Comptes et du Logiciel Libre
Ludovic QUENECHDU est un véritable virtuose de la virtualisation et de la sécurité informatique. Depuis son indépendance professionnelle en 2000, il a apporté son expertise à de prestigieux clients tels que Cameroun Telecom, Merryl Lynch, Ernst & Young, AXA, et bien d'autres. En parallèle, Ludovic s'engage régulièrement dans le démarrage de petites entreprises, notamment dans le domaine du logiciel libre, une passion qu'il chérit pour ses valeurs de partage et d'échange. Son parcours professionnel et sa passion pour la technologie en font un acteur incontournable de l'industrie informatique.
5 commentaires