Docker avec Dnsdock

Au cours de mes projets s'est posée la problématique suivante : comment communiquer simplement avec mes containers Docker ?

L'idéal serait de pouvoir appeler un container par le même nom, depuis Docker ou ma machine hôte. Ainsi, l'exécution d'un script tel que bin/console fonctionnerait car arriverait à communiquer correctement avec les containers dépendants (base de données, services annexes…).

Une première solution s'offre à nous : l'image Docker jwilder/nginx-proxy propose un proxy HTTP qui, grâce à un minimum de configuration, permet de nommer des containers. Seulement voilà, cela ne concerne pas les services TCP tels que MySQL, ElasticSearch ou encore RabbitMQ…

En fouillant d'avantage, j'ai alors trouvé Dnsdock, une image Docker proposant un serveur DNS avec découverte automatique des containers nommés.

Pré-requis

Pour suivre ce tutoriel, il est recommandé d'avoir de bonnes connaissances en Docker.

Mise en place de Dnsdock

Pour fonctionner, Dnsdock doit écouter le réseau Docker sur lequel il tourne. Dans notre exemple, nous pouvons utiliser le réseau bridge de Docker. La commande suivante permet de récupérer l'adresse IP de sa gateway :

docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge  

Dans un environnement sous Docker Toolbox, cette adresse IP est 172.17.0.1. Dans tout autre environnement, pensez à l'adapter dans la suite de ce tutoriel.

Il est maintenant possible de lancer Dnsdock à l'écoute de ce réseau :

docker run -d -v /var/run/docker.sock:/var/run/docker.sock --name dnsdock -p 172.17.0.1:53:53/udp aacebedo/dnsdock:v1.16.1-amd64 --domain local  

Notez l'utilisation de l'expression --domain local : celle-ci va demander à Dnsdock d'écouter le nom de domaine *.local.

C'est bien beau, mais je dois quand même mettre à jour mon fichier /etc/hosts avec les alias de tous mes containers…

C'est là que le resolver entre en action ! Sous un environnement Unix, vous disposez d'un petit atout réseau vous permettant de rediriger un nom de domaine vers une adresse IP.

Configuration du resolver

Sous Linux, éditez votre fichier /etc/resolv.conf pour y ajouter les lignes suivantes :

domain local  
nameserver 172.17.0.1  

Sous OS X, créez le fichier /etc/resolver/local contenant la ligne suivante :

nameserver 172.17.0.1  

Dans un environnement Docker Toolbox, il est nécessaire de rerouter cette adresse IP vers votre machine Docker : sudo route -n add -net 172.17.0.0 192.168.99.100.

Note: n'ayant pas pu tester cette configuration sous Windows, je suis ouvert à tout retour sur ce point.

Configuration des containers

Dnsdock tourne et écoute correctement le réseau, il est maintenant possible de nommer nos containers. 2 configurations sont cependant nécessaires : un label (requis par Dnsdock), et un network alias (pour Docker) :

docker run --label mysql.local mysql  

Bonus : Docker Compose

En bonus, voici un exemple de fichier docker-compose.yml implémentant Dnsdock dans un réseau Docker privé, avec différents containers. Il ne vous restera plus qu'à configurer le resolver pour le nom de domaine *.foo :

version: '2'

volumes:  
    db: ~

networks:  
    default:
        ipam:
            config:
                - subnet: 172.36.200.0/24
                  gateway: 172.36.200.1

services:  
    dnsdock:
        image: aacebedo/dnsdock:v1.16.1-amd64
        command: --domain foo
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
        ports:
            - 172.36.200.1:53:53/udp

    api:
        build: api/
        environment:
            DB_HOST: db.example.foo
            MAILER_HOST: mail.example.foo
        volumes:
            - api/:/app
        networks:
            default:
                aliases:
                    - api.example.foo
        labels:
            com.dnsdock.alias: api.example.foo

    spa:
        build: spa/
        environment:
            API_HOST: api.example.foo
        volumes:
            - spa/:/app
        networks:
            default:
                aliases:
                    - www.example.foo
        labels:
            com.dnsdock.alias: www.example.foo

    db:
        image: wangxian/alpine-mysql:edge
        environment:
            MYSQL_USER: foo
            MYSQL_PASSWORD: p4$$w0rd
            MYSQL_DATABASE: bar
        volumes:
            - db:/var/lib/mysql:rw
        networks:
            default:
                aliases:
                    - db.example.foo
        labels:
            com.dnsdock.alias: db.example.foo

    mailcatcher:
        image: tophfr/mailcatcher:0.6.5
        networks:
            default:
                aliases:
                    - mail.example.foo
        labels:
            com.dnsdock.alias: mail.example.foo