Dans l'article précédent sur l'aiguillage DNS nous
avons demandé la résolution DNS au serveur dnsmasq écoutant sur 127.0.0.1
.
Problème, les conteneurs Docker ont basculé sur le serveur DNS 8.8.8.8
au lieu
d'utiliser la résolution DNS du réseau interne. Les conteneurs envoient leurs
requêtes DNS à Google. Pourquoi ??
Lorsque le moteur Docker cherche un serveur DNS pour ses conteneurs, impossible
d'utiliser l'adresse 127.0.0.1
puisque les conteneurs sont dans un réseau
isolé. L'adresse 127.0.0.1
est ignorée. Le moteur Docker ne trouvant pas de
serveur résolvable, il bascule sur Google DNS.
Outre passer par Google, cette configuration empêche vos conteneurs de résoudre les domaines privés comme par exemple une instance interne de Warehouse.
La solution s'impose : il faut exposer dnsmasq
sur une IP routable. Routable
ne veut pas dire publique. Il suffit juste qu'elle ne commence pas par 127.
.
Partager dnsmasq
avec les conteneurs Docker
Première étape, monter une interface réseau virtuelle et lui associer une IP
routable. Pour le besoin, j'ai pris 192.168.7.1
. Je vais présenter comment
configurer ça dans Debian, on peut aussi le faire avec systemd-networkd
, mais
c'est un poil plus compliqué.
D'abord, créer le fichier /etc/network/interfaces.d/dockerdns0
comme suivant :
~ # cat > /etc/network/interfaces.d/dockerdns
# Créer une interface dummy
auto dockerdns0
iface dockerdns0 inet manual
pre-up ip link add $IFACE type dummy
pre-up ip link set dev $IFACE up
post-down ip link set dev $IFACE down || true
post-down ip link delete dev $IFACE type dummy || true
# Configurer une adresse IP statique
iface dockerdns0 inet static
netmask 255.255.255.0
address 192.168.7.1
~ # sudo ifup dockerdns0
~ # ip address show dev dockerdns0
5: dockerdns0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether de:2e:54:a0:3f:f7 brd ff:ff:ff:ff:ff:ff
inet 192.168.7.1/24 brd 192.168.7.255 scope global dockerdns0
valid_lft forever preferred_lft forever
inet6 fe80::dc2e:54ff:fea0:3ff7/64 scope link
valid_lft forever preferred_lft forever
~ #
Parfait ! Maintenant, il faut que notre dnsmasq
écoute sur le port UDP 53 de
l'adresse 192.168.7.1
. Voici comment configurer dnsmasq
:
~ # cat > /etc/dnsmasq.d/docker.conf
listen-address=192.168.7.1
~ # systemctl restart dnsmasq
~ # host cae.li 192.168.7.1
Using domain server:
Name: 192.168.7.1
Address: 192.168.7.1#53
Aliases:
cae.li has address 54.36.101.202
~ #
Ça fonctionne. Reste à indiquer au moteur Docker de l'utiliser. En bon citoyen
de notre système, Docker lit les serveurs DNS dans resolv.conf
. On va donc
notifier resolvconf
pour utiliser ce serveur en ajoutant un post-up
et un
post-down
à la configuration de l'interface.
# /etc/network/interfaces.d/dockerdns
iface dockerdns0 inet static
netmask 255.255.255.0
address 192.168.7.1
post-up echo nameserver 192.168.7.1 | resolvconf -a lo.inet
post-down resolvconf -d lo.inet || true
Les commandes post-up
et post-down
indiquent à resolvconf
qu'un nouveau
serveur DNS est disponible. On associe l'IP 192.168.7.1
à lo.inet
pour
prendre le pas sur lo.dnsmasq
dans l'ordre des nameserver
du fichier
resolv.conf
. En fait, tout notre système interrogera dnsmasq
via cette IP
désormais. Cf. interface-order(1)
.
Il faut redémarrer le moteur Docker avec systemctl restart docker
. Pour
valider ça, on va résoudre un nom de domaine interne dans un conteneur ad-hoc :
$ docker run --rm alpine:latest getent hosts registry.lan.mycompany.net
10.0.12.1 registry.lan.mycompany.net
$
Voilà ! Maintenant la configuration DNS est unifiée entre le système et les
conteneurs. Les conteneurs vont profiter du cache DNS et de l'aiguillage.
Prochaine étape, résoudre les conteneurs avec le domaine .docker
!