Configurer automatiquement Nginx avec Docker et Docker-gen

Dans cet article, je vous propose de mettre en place un serveur web NGINX qui va servir de frontal pour vos différents conteneurs Docker.

La solution retenu permet de configurer automatiquement NGINX à partir des images et containers démarrés par Docker sans opération manuelle de votre part sur Nginx. Nous utilisons l’outil docker-gen pour la configuration de nginx. Un deuxième article sera bientôt disponible pour activer https et vous aider à gérer les certificats automatiquement avec Let’s Encrypt

docker-gen

Docker Gen est un générateur de fichier qui se base sur les métadonnées obtenus sur les containers lancés sur votre machine. Docker-gen va utiliser les informations liées au container ( docker inspect) pour récupérer les variables d’environnements, les ports exposés et les adresses ip des containers. A partir de ces informations, docker-gen va générer un fichier à partir d’un fichier de template de départ.

Projet Github : https://github.com/jwilder/docker-gen

Dans notre exemple, nous allons utiliser cet utilitaire pour générer le fichier de conf de NGINX, mais il peux s’adapter à de très nombreux besoins:

  • Configuration des reverses proxy (Nginx, Apache, HAProxy)
  • Gestion des logs
  • Service Discovery
  • Générateur de documentation

Docker-gen fonctionne soit en ligne de commande, soit sous la forme d’une image Docker.

Voici le fichier docker-compose permettant de lancer nginx et l’image nginx_gen

nginx:
    image: nginx:1.11
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./generated/nginx/conf.d:/etc/nginx/conf.d
      - ./generated/nginx/html:/usr/share/nginx/html
      - ./templates:/etc/docker-gen/templates
  nginx_gen:
    image: jwilder/docker-gen
    container_name: nginx-gen
    volumes_from: 
      - nginx
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./templates:/etc/docker-gen/templates:ro
    links:
     - nginx
    entrypoint: /usr/local/bin/docker-gen -notify-sighup nginx -watch -only-exposed -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf

Le container docker-gen va surveiller en permance le lancement et l’extinction des conteneurs sur votre machine. A chaque changement, nginx-gen analysera les variables environnement des containers lancés et générera un nouveau fichier default.conf à partir du fichier de template nginx.tmpl.

Une fois le fichier de configuration généré, le entrypoint indique qu’il au container qu’il doit faire une notification à NGINX pour recharger à chaud sa configuration.

Pour information, il existe aussi une image jwilder/nginx-proxy qui hérite de Nginx et intègre automatiquement docker-gen. L’image simplifie la configuration et évite de lancer plusieurs containers. Cela peux répondre à des besoins simples, mais vous ne pourrez pas surcharger le fichier template par défaut. De plus, l’image nécessite de donner accès en lecture seul au socket /var/run/docker.sock à un container qui sert de frontal et qui est exposé sur internet. C’est pour cette raison sécuritaire que je préfère utiliser 2 images distincts

Fichier de template

Voici un exemple de fichier template (la version complète du fichier est fournit dans le repo git)

{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
	upstream {{ $host }} {
		{{ range $index, $value := $containers }}
			{{ with $address := index $value.Addresses 0 }}
				# {{$value.Name}}
				server {{ $network.IP }}:{{ $address.Port }};
			{{ end }}
		{{ end }}
	}
{{ end }}

Et voici l’explication, pour chaque container identifié avec une variable d’environnement « VIRTUAL_HOST », ajouter dans l’instruction nginx upstream la liste des toutes les adresses ip des containers docker.

Voici maintenant comment démarrer votre propre container en y ajoutant la variable d’environnement adaptée

  tomcat:
    image: tomcat:8.0
    environment:
     - VIRTUAL_HOST=tomcat.demo.w3blog.fr

Dans notre exemple, nous générons des sous-domaines, mais si vous connaissez le fonctionnement d’une configuration nginx, vous pourrez très facilement adapter le template pour gérer des sous-répertoires ou n’importe quel configuration plus complexe.

Une fois l’outil docker-gen pris en main, les possibilités offertes par ce simple outil en ligne de commande sont énormes. Pour répondre à une problématique de scalabilité, nous avons utiliser docker-gen pour ajouter automatiquement les adresses ip d’une même image lancé plusieurs fois et ainsi faire du load-balancing avec nginx.

Dans un prochaine article, nous ajouterons à cette exemple une configuration automatique de vos certificats Let’s encrypt.