Que fait vraiment l'option --net = host dans la commande Docker?

90

Je suis un peu débutant dans Docker. Je n'ai pas trouvé de description claire de ce que fait cette option dans la commande docker run en profondeur et un peu confus à ce sujet.

Pouvons-nous l'utiliser pour accéder aux applications exécutées sur des conteneurs Docker sans spécifier de port? À titre d'exemple, si j'exécute une application web déployée via une image docker dans le port 8080 en utilisant l'option -p 8080:8080dans la commande docker run, je sais que je devrai y accéder sur le port 8080 sur les conteneurs Docker ip / theWebAppName. Mais je ne peux pas vraiment penser à une façon dont l' --net=hostoption fonctionne.

Ravindu Fernando
la source

Réponses:

127

Après l'installation du docker, vous disposez de 3 réseaux par défaut:

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f3be8b1ef7ce        bridge              bridge              local
fbff927877c1        host                host                local
023bb5940080        none                null                local

J'essaie de garder cela simple. Donc, si vous démarrez un conteneur par défaut, il sera créé à l'intérieur du réseau du pont (docker0).

$ docker run -d jenkins
1498e581cdba        jenkins             "/bin/tini -- /usr..."   3 minutes ago       Up 3 minutes        8080/tcp, 50000/tcp   friendly_bell

Dans le fichier docker de jenkins, les ports 8080et 50000sont exposés. Ces ports sont ouverts pour le conteneur sur son réseau de pont. Ainsi, tout ce qui se trouve à l'intérieur de ce réseau de pont peut accéder au conteneur sur le port 8080et 50000. Tout dans le réseau de pont est dans la plage privée de "Subnet": "172.17.0.0/16",Si vous souhaitez y accéder de l'extérieur, vous devez mapper les ports avec -p 8080:8080. Cela mappera le port de votre conteneur sur le port de votre serveur réel (le réseau hôte). Ainsi, accéder à votre serveur sur 8080sera acheminé vers votre réseau de ponts sur le port 8080.

Maintenant, vous avez également votre réseau hôte. Ce qui ne conteneurise pas la mise en réseau des conteneurs. Donc, si vous démarrez un conteneur dans le réseau hôte, il ressemblera à ceci (c'est le premier):

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
1efd834949b2        jenkins             "/bin/tini -- /usr..."   6 minutes ago       Up 6 minutes                              eloquent_panini
1498e581cdba        jenkins             "/bin/tini -- /usr..."   10 minutes ago      Up 10 minutes       8080/tcp, 50000/tcp   friendly_bell

La différence est avec les ports. Votre conteneur est maintenant à l'intérieur de votre réseau hôte. Donc, si vous ouvrez le port 8080sur votre hôte, vous accéderez immédiatement au conteneur.

$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT

J'ai ouvert le port 8080dans mon pare-feu et quand j'accède maintenant à mon serveur sur le port, 8080j'accède à mes jenkins. Je pense que ce blog est également utile pour mieux le comprendre.

lvthillo
la source
4
Est-il possible d'ajouter l'option --net=hostdans un Dockerfile?
AnirbanDebnath
6
@AnirbanDebnath Je ne pense pas qu'il soit possible de le mettre dans un dockerfile mais comme docker V17 vous pouvez l' utiliser comme paramètre pour votre build docker: docker build --network=host. Le réseau hôte spécifié pour la construction de docker sert uniquement au téléchargement des packages nécessaires à la création de l'image. Lorsque vous souhaitez exécuter votre conteneur sur le réseau hôte, vous devez toujours définir l'option --network = host.
lvthillo
Oui @AnirbanDebnath, c'est autorisé dans Dockerfile. Par exemple, en v3 - network_mode: "host"(ref - docs.docker.com/compose/compose-file/#network_mode )
Mohnish
C'est un fichier Docker-Compose qui décrit comment exécuter le conteneur. Pas un Dockerfile. Mais en effet, là c'est possible et fait la même chose que docker run --network = host
lvthillo
27

L' --net=hostoption est utilisée pour donner l'impression que les programmes à l'intérieur du conteneur Docker s'exécutent sur l'hôte lui-même, du point de vue du réseau. Il permet au conteneur un meilleur accès au réseau qu'il ne peut en obtenir normalement.

Normalement, vous devez transférer les ports de la machine hôte vers un conteneur, mais lorsque les conteneurs partagent le réseau de l'hôte, toute activité réseau se produit directement sur la machine hôte - tout comme si le programme s'exécutait localement sur l'hôte au lieu de l'intérieur d'un récipient.

Bien que cela signifie que vous n'avez plus à exposer les ports et à les mapper aux ports de conteneurs, cela signifie que vous devez modifier vos Dockerfiles pour ajuster les ports sur lesquels chaque conteneur écoute, pour éviter les conflits car vous ne pouvez pas avoir deux conteneurs fonctionnant sur le même port hôte. Cependant, la vraie raison de cette option est d'exécuter des applications qui ont besoin d'un accès réseau difficile à transmettre à un conteneur au niveau du port.

Par exemple, si vous souhaitez exécuter un serveur DHCP, vous devez être en mesure d'écouter le trafic de diffusion sur le réseau et d'extraire l'adresse MAC du paquet. Ces informations sont perdues pendant le processus de transfert de port, donc la seule façon d'exécuter un serveur DHCP dans Docker est d'exécuter le conteneur en tant que --net=host.

D'une manière générale, cela --net=hostn'est nécessaire que lorsque vous exécutez des programmes avec des besoins réseau très spécifiques et inhabituels.

Enfin, du point de vue de la sécurité, les conteneurs Docker peuvent écouter sur de nombreux ports, même s'ils n'annoncent (exposent) qu'un seul port. Normalement, cela convient car vous ne transférez que le port attendu unique, mais si vous l'utilisez, --net=hostvous obtiendrez tous les ports du conteneur à l'écoute sur l'hôte, même ceux qui ne sont pas répertoriés dans le Dockerfile. Cela signifie que vous devrez vérifier attentivement le conteneur (surtout s'il ne s'agit pas du vôtre, par exemple un conteneur officiel fourni par un projet logiciel) pour vous assurer de ne pas exposer par inadvertance des services supplémentaires sur la machine.

Malvineous
la source
Quel serait le comportement si plusieurs conteneurs sont démarrés avec les options '--net = host'? Les demandes seront-elles transmises à un conteneur aléatoire?
user482594
@ user482594: Ils partageront tous la même pile réseau, tout comme vous avez exécuté tous les programmes dans le même conteneur. Par exemple, si vous exécutez deux serveurs Web, vous devrez vous assurer qu'ils écoutent sur des ports différents, sinon le deuxième conteneur recevra une erreur indiquant que le port est utilisé par le premier. Le trafic entrant sera redirigé vers le conteneur qui l'écoute (techniquement, tous les --net=hostconteneurs verront le trafic, mais bien sûr, un seul programme à la fois peut écouter sur un port donné, quel que soit le conteneur dans lequel vous l'exécutez, dans cette configuration ).
Malvineous
1
  1. vous pouvez créer votre propre nouveau réseau comme --net = "anyname"
  2. ceci est fait pour isoler les services de différents conteneurs.
  3. supposons que le même service s'exécute dans différents conteneurs, mais que le mappage de port reste le même, le premier conteneur démarre bien, mais le même service du second conteneur échouera. pour éviter cela, modifiez les mappages de ports ou créez un réseau.
Abhishek DK
la source
1
Merci de mentionner "2. ceci est fait pour isoler les services (réseau) de différents conteneurs". Je vois vraiment l'intérêt d'utiliser d'autres configurations de réseau docker (autres que host) s'il est possible d'exécuter plusieurs conteneurs sur le même hôte. Dans d'autres cas (où l'isolation du réseau n'est pas requise), je préférerais --net=host.
CᴴᴀZ