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.]+'
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
.
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
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
Utilisez --net="Host"
dans votre commande docker run
, puis localhost
dans votre conteneur de menu fixe indiquera votre hôte de menu fixe.
Solution avec docker-compose: Pour accéder au service basé sur l'hôte, vous pouvez utiliser le paramètre network_mode
https://docs.docker.com/compose/compose-file/#network_mode
version: '3'
services:
jenkins:
network_mode: Host
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).
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
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.
Vous pouvez accéder au serveur Web local en cours d'exécution sur votre ordinateur hôte de deux manières.
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.
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
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.
J'ai exploré les différentes solutions et je trouve que c'est la solution la moins compliquée:
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".