web-dev-qa-db-fra.com

Comment accéder au port de l'hôte à partir du conteneur de menu fixe

J'ai un conteneur docker exécutant Jenkins. Dans le cadre du processus de construction, je dois accéder à un serveur Web exécuté localement sur la machine hôte. Le serveur Web hôte (pouvant être configuré pour s'exécuter sur un port) peut-il être exposé au conteneur Jenkins?

EDIT: J'exécute docker en mode natif sur une machine Linux.

METTRE À JOUR:

En plus de la réponse @larsks ci-dessous, pour obtenir l'adresse IP de l'hôte IP de la machine hôte, procédez comme suit:

ip addr show docker0 | grep -Po 'inet \K[\d.]+'
142
Tri Nguyen

Lors de l'exécution native de Docker sur Linux, vous pouvez accéder aux services de l'hôte à l'aide de l'adresse IP de l'interface docker0. Depuis l'intérieur du conteneur, ce sera votre route par défaut.

Par exemple, sur mon système:

$ ip addr show docker0
7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 00:00:00:00:00:00 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::f4d2:49ff:fedd:28a0/64 scope link 
       valid_lft forever preferred_lft forever

Et à l'intérieur d'un conteneur:

# ip route show
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0  src 172.17.0.4 

Il est assez facile d'extraire cette adresse IP en utilisant un simple script Shell :

#!/bin/sh

hostip=$(ip route show | awk '/default/ {print $3}')
echo $hostip

Vous devrez peut-être modifier les règles iptables sur votre hôte pour autoriser les connexions À partir de conteneurs Docker. Quelque chose comme ça fera l'affaire

# iptables -A INPUT -i docker0 -j ACCEPT

Cela permettrait l'accès à tous les ports de l'hôte à partir de conteneurs Docker Notez que:

  • les règles iptables sont ordonnées, et cette règle peut faire ou non la bonne chose, selon ce que les autres règles ont avant.

  • vous ne pourrez accéder qu'aux services de l'hôte qui écoutent (a) sur INADDR_ANY (ou 0.0.0.0) ou qui écoutent explicitement sur l'interface docker0.

121
larsks

Pour macOS et Windows

Docker v 18.03 et plus (depuis le 21 mars 2018)

Utilisez votre adresse IP interne ou connectez-vous au nom DNS spécial Host.docker.internal qui résoudra en adresse IP interne utilisée par l'hôte.

Prise en charge de Linux en attente https://github.com/docker/for-linux/issues/264

MacOS avec les versions antérieures de Docker

Docker pour Mac v 17.12 à 18.02

Comme ci-dessus mais utilisez plutôt docker.for.mac.Host.internal.

Docker pour Mac v 17.06 à 17.11

Comme ci-dessus mais utilisez plutôt docker.for.mac.localhost.

Docker pour Mac 17.05 et inférieur

Pour accéder à la machine hôte à partir du conteneur de menu fixe, vous devez associer un alias IP à votre interface réseau. Vous pouvez associer l'adresse IP de votre choix, assurez-vous simplement que vous ne l'utilisez pas pour autre chose.

Sudo ifconfig lo0 alias 123.123.123.123/24 

Assurez-vous ensuite que votre serveur écoute l'adresse IP mentionnée ci-dessus ou 0.0.0.0. S'il écoute sur localhost 127.0.0.1, il n'acceptera pas la connexion.

Ensuite, pointez simplement votre conteneur docker vers cette adresse IP et vous pourrez accéder à la machine hôte!

Pour tester, vous pouvez exécuter quelque chose comme curl -X GET 123.123.123.123:3000 à l'intérieur du conteneur.

L'alias sera réinitialisé à chaque redémarrage, alors créez un script de démarrage si nécessaire.

Solution et plus de documentation ici: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds

161
Janne Annala

Utilisez --net="Host" dans votre commande docker run, puis localhost dans votre conteneur de menu fixe indiquera votre hôte de menu fixe.

21
samthebest

Solution avec docker-compose: Pour accéder au service basé sur l'hôte, vous pouvez utiliser le paramètre network_modehttps://docs.docker.com/compose/compose-file/#network_mode

version: '3'
services:
  jenkins:
    network_mode: Host
7
vovan

Actuellement, le moyen le plus simple de le faire sur Mac et Windows consiste à utiliser Host Host.docker.internal , qui résout l'adresse IP de l'ordinateur hôte. Malheureusement, il ne fonctionne pas encore sur linux (à partir d'avril 2018). 

6
Tomáš Fejfar

J'ai créé un conteneur Docker pour faire exactement cela https://github.com/qoomon/docker-Host

Vous pouvez ensuite simplement utiliser le nom de conteneur dns pour accéder au système hôte, par exemple. curl http://dockerhost:9200

2
qoomon

Nous avons constaté qu'une solution plus simple à tous ces problèmes de réseautage consiste simplement à utiliser la socket de domaine pour le service. Si vous essayez quand même de vous connecter à l'hôte, montez simplement le socket en tant que volume et vous êtes prêt. Pour postgresql, c'était aussi simple que:

docker run -v /var/run/postgresql:/var/run/postgresql

Ensuite, nous venons de configurer notre connexion de base de données pour utiliser le socket au lieu du réseau. Littéralement aussi facile.

1
mlissner

Vous pouvez accéder au serveur Web local en cours d'exécution sur votre ordinateur hôte de deux manières.

  1. Approche 1 avec IP publique

    Utilisez l'adresse IP publique de la machine hôte pour accéder au serveur Web dans le conteneur de menu fixe Jenkins.

  2. Approche 2 avec le réseau hôte

    Utilisez "--net Host" pour ajouter le conteneur de menu fixe Jenkins sur la pile réseau de l'hôte. Les conteneurs déployés sur la pile de l'hôte ont un accès complet à l'interface de l'hôte. Vous pouvez accéder au serveur Web local dans le conteneur de menu fixe avec une adresse IP privée de la machine hôte.

NETWORK ID          NAME                      DRIVER              SCOPE
b3554ea51ca3        bridge                    bridge              local
2f0d6d6fdd88        Host                      Host                local
b9c2a4bc23b2        none                      null                local

Démarrez un conteneur avec l'hôte networkcode Eg: docker run --net Host -it ubuntu et exécutez ifconfig pour répertorier toutes les adresses IP réseau disponibles qui sont accessibles à partir du conteneur docker.

Exemple: j'ai démarré un serveur nginx sur mon ordinateur hôte local et je peux accéder aux URL du site Web nginx à partir du conteneur de menu fixe Ubuntu.

docker run --net Host -it ubuntu

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
a604f7af5e36        ubuntu              "/bin/bash"         22 seconds ago      Up 20 seconds                           ubuntu_server

Accès au serveur Web Nginx (exécuté sur la machine hôte locale) à partir du conteneur de menu fixe Ubuntu avec adresse IP de réseau privé.

root@linuxkit-025000000001:/# curl 192.168.x.x -I
HTTP/1.1 200 OK
Server: nginx/1.15.10
Date: Tue, 09 Apr 2019 05:12:12 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Mar 2019 14:04:38 GMT
Connection: keep-alive
ETag: "5c9a3176-264"
Accept-Ranges: bytes
0
sreenivasar

Lorsque vous avez deux images de menu fixe "déjà" créées et que vous souhaitez placer deux conteneurs pour communiquer l'un avec l'autre.

Pour cela, vous pouvez facilement exécuter chaque conteneur avec son propre --name et utiliser l'indicateur --link pour permettre la communication entre eux. Vous ne recevez pas cela pendant la construction du docker.

Quand vous êtes dans un scénario comme moi, et que c'est votre 

docker build -t "centos7/someApp" someApp/ 

Ça casse quand tu essaies de

curl http://172.17.0.1:localPort/fileIWouldLikeToDownload.tar.gz > dump.tar.gz

et vous êtes bloqué sur "curl/wget" ne renvoyant aucune "route à l'hôte".

La raison en est une sécurité mise en place par docker qui, par défaut, interdit la communication d’un conteneur vers l’hôte ou d’autres conteneurs s'exécutant sur votre hôte ... C'est assez surprenant pour moi, je dois dire que vous vous attendriez à ce que l'écosystème des machines fixes fonctionnant sur une machine locale peuvent parfaitement se connecter sans trop d’obstacles.

L'explication de cela est décrite en détail dans la documentation suivante.

http://www.dedoimedo.com/computers/docker-networking.html

Deux solutions de contournement rapides vous sont proposées pour vous aider à bouger en réduisant la sécurité du réseau.

La solution la plus simple consiste simplement à désactiver le pare-feu ou à tout autoriser. Cela signifie qu’il faut exécuter la commande nécessaire, qui peut être systemctl stop firewalld, iptables -F ou l’équivalent.

J'espère que cette information vous aide.

0
99Sono

J'ai exploré les différentes solutions et je trouve que c'est la solution la moins compliquée:

  1. Définissez une adresse IP statique pour l'adresse IP de la passerelle de pont.
  2. Ajoutez l'adresse IP de la passerelle en tant qu'entrée supplémentaire dans le fichier hosts.

Le seul inconvénient est que, si plusieurs réseaux ou projets le font, vous devez vous assurer que leur plage d'adresses IP n'entre pas en conflit.

Voici un exemple de Docker Compose:

version: '2.3'

services:
  redis:
    image: "redis"
    extra_hosts:
      - "dockerhost:172.20.0.1"

networks:
  default:
    ipam:
      driver: default
      config:
      - subnet: 172.20.0.0/16
        gateway: 172.20.0.1

Vous pouvez ensuite accéder aux ports de l'hôte depuis l'intérieur du conteneur en utilisant le nom d'hôte "dockerhost".

0
bcoughlan