Favrice

De Zbeulist
Aller à : navigation, rechercher

Favrice

Explication Numéro Un

Ici j'essaie de dire comment ça marche ce qui tourne sur Favrice, le serveur au 211 gros hébergeant pas mal de truc *.zbeul.ist. C'est orienté Docker. Je vais pas expliquer comment ça marche docker y'a des gens qui font ça mieux, mais plutôt comment ça communique ici particulièrement, et comment faire tourner un truc en plus sur Favrice.

Qu'est-ce qui se passe

Chaque sous domaine qui tourne sur favrice correspond à une application différente. Toutes les requêtes web extérieur arrivent sur le même serveur qui s'occupe de dispatcher aux bonnes applications derrières (wiki.zbeul.ist -> mediawiki, pic.zbeul.ist -> lutim). C'est le reverse-proxy. Après, chaque application gère comme elle veut cette requête, avec des fois un serveur web qui interprète du php, des fois une application en fortran, tant que ça gère la connexion et donne des pages web.

De plus, le reverse-proxy s'occupe aussi de chiffrer/déchiffrer le trafic et récupérer des certificats chez let's encrypt. Donc ça fait :

 Exterieur <===[Chiffré]===> Reverse-proxy <===[Non chiffré]===> Appli

Avec docker et tout

Sous docker, chaque application est un conteneur qui contient un os minimal pour faire tourner son application isolée du reste. Le reverse-proxy est lui-même un conteneur. Mediawiki est un ensemble de 2 conteneurs (un qui fait l'appli, un qui stocke les données).

Là où ça devient cool c'est que c'est assez automatisé. Le reverse-proxy ici c'est caddy-proxy, qui se base sur le serveur web caddy.

Quand on lance un conteneur, on a plein de paramètre dont des variables d’environnement. Quand on lance un nouveau conteneur, caddy-proxy va alors inspecter les variables d'environnement et chercher une qui s'appelle "VIRTUAL_HOST", qui aurait pour valeur un truc genre "bla.zbeul.ist". Si il y en a une, il va interroger let's encrypt pour avoir un certificat, puis ensuite rediriger les requête pour bla.zbeul.ist vers ce nouveau conteneur.

Concrètement, lancer caddy-proxy c'est à peu près ça (vérifie pas, ptetre je me suis planté quelque part) :

 docker run -d --name web-proxy -p "80:80" -p "443" \
       -v /var/run/docker.sock:/tmp/docker.sock:ro  \
       -v /srv/caddy:/root/.caddy                   \
       -e "CADDY_OPTIONS=--email housemaster@zbeul.ist" blackglory/caddy-proxy
  • -d : Mode détaché, pour qu'il te rende la main après.
  • --name : Nom de l'image crée. Une fois lancé, docker fait office de dns aussi, les conteneurs peuvent communiquer entre elle par leur nom.
  • -p "80:80" : Publier le port 80 (http) du conteneur. Donc maintenant si on se connecte sur favrice, le port 80 de favrice est renvoyé sur le port 80 de docker-proxy.
  • -p "443:443" : Idem pour 443 (https).
  • -v /var/run/docker.sock:/tmp/docker.sock:ro : Comme les ports, mais pour les fichiers. Ça mappe le fichier interne au conteneur /tmp/docker.sock au fichier externe /var/run/docker.sock. Ça lui sert à surveiller les nouveaux conteneurs qui arrivent.
  • -v /srv/caddy:/root/.caddy : Mapper le vrai dossier /srv/caddy au dossier /root/.caddy du conteneur. C'est ici qu'il stocke les certificats. Comme ça, si je détruit complètement l'image, puis la relance, j'ai perdu aucun certificat.
  • -e "CADDY_OPTIONS=--email housemaster@zbeul.ist" : Assignation d'une variable d'environnement. C'est pour let's encrypt celle là.
  • blackglory/caddy-proxy : Le nom de l'image qui va faire tourner le conteneur.

Tout ce merdier est généralement documenté sur la page de l'image. Généralement.

À noter que l'image "expose" certain port, qu'on peut choisir de "publier" ou nom. Ici on a publié ses deux ports 80 et 443.

Ensuite, si on rajoute un service, genre zerobin, ça ressemble à ça :

 docker run -d --name zerobin -e VIRTUAL_HOST=txt.zbeul.ist -v /srv/zerobin:/zerobin/data

Et bim, caddy-proxy voit un nouveau conteneur qui a la variable VIRTUAL_HOST=txt.zbeul.ist, va, si c'est pas déjà fait, interroger let's encrypt et faire les checks pour vérifier qu'il est bien sur txt.zbeul.ist, activer tout ça, et on va pouvoir y accéder.

Les lignes de commande docker ça part vite en live, par exemple mediawiki stocke ses données sur un conteneur séparé de base de donnée :

 docker run --name some-mediawiki -e VIRTUAL_HOST=wiki.zbeul.ist \
                                  -e MEDIAWIKI_DB_HOST=10.0.0.1:3306 \
                                  -e MEDIAWIKI_DB_USER=app \
                                  -e MEDIAWIKI_DB_PASSWORD=secure synctree/mediawiki
 docker run --name some-mediawiki --link some-mysql:mysql -p 8080:80 -d synctree/mediawiki

Ici il y a un truc nouveau, c'est --link. Ça permet d'exposer les variables d'un conteneur dans un autre, c'est souvent utilisé pour partager les noms d'utilisateurs/mdp d'une base de données.

Docker Compose

Pour stocker ces lignes de commande, il y a docker-compose, qui permet de définir dans un fichier toutes les options de lancement d'une ou plusieurs images.

Pour zerobin, ça donne un truc comme ça :

zerobin:
  image: wonderfall/zerobin
  restart: unless_stopped
  environment:
    - VIRTUAL_HOST=txt.zbeul.ist
  volumes:
    - /srv/zerobin:/zerobin/data

Pour mediawiki :

mediawiki:
   image: simplyintricate/mediawiki
   restart: unless-stopped
   links:
     - db
   volumes:
     - /srv/mediawiki/LocalSettings.php:/usr/share/nginx/html/LocalSettings.php
     - /media/favrice/mediawiki/images:/usr/share/nginx/html/images
     - /srv/mediawiki/extensions:/usr/share/nginx/html/extensions
     - /srv/mediawiki/conf.d:/etc/nginx/conf.d
   environment:
     - VIRTUAL_HOST=wiki.zbeul.ist
db:
   image: mysql
   restart: unless-stopped
   env_file: secrets.env # MYSQL_ROOT_PASSWORD

(Cherche pas c'est pas la même config qu'au dessus).

Là où c'est pas mal, c'est que docker-compose fait un espace de nommage d'images. Donc là, on aura en vrai mediawiki_mediawiki et mediawiki_db. Donc pas de collision de noms.

Donc jusqu'ici tout va bien, c'est les commandes de docker run écrites autrement. On suit les infos de la personne qui a fait l'image, on met ça dans un fichier docker-compose.yaml, on fait docker-compose up -d, et c'est parti.

Docker Compose v2

Sauf que ce fichier, c'est un docker-compose format v1, qui est déprécié et va bientôt plus être supporté :(

Ils ont fait un format v2, qui intègre des nouvelles fonctions de docker, à savoir des volumes virtuels, des réseaux virtuels.

La manière dont ils ont implémenté ça, c'est que chaque fichier docker-compose crée son propre réseau virtuel, et ne peut donc communiquer qu'avec ceux qui sont dans le même. C'est bien mais c'est chiant, parce que ça nous pète notre reverse-proxy qui ne peut plus communiquer avec les autres. Il y a plein de workaround, avec un réseau crée dans docker qui est partagé à tous, mais c'est plus chiant à écrire, et j'ai jamais réussi à le faire marcher. L'alternative, c'est de tous leur dire "network_mode: bridge", et hop tout le monde de retour dans le même réseau. On ne peut donc pas utiliser ces nouvelles fonctions, mais on s'en passera.

Donc maintenant, ces deux fichiers ressemblent à ça :

Zerobin :

 version: '2' 
 services:
   zerobin:
     image: wonderfall/zerobin
     restart: unless_stopped
     network_mode: bridge
     environment:
       - VIRTUAL_HOST=txt.zbeul.ist
     volumes:
       - /srv/zerobin:/zerobin/data

Mediawiki :

 version: "2"
 services:
   mediawiki:
     image: simplyintricate/mediawiki
     restart: unless-stopped
     network_mode: bridge
     links:
       - db
     volumes:
       - /srv/mediawiki/LocalSettings.php:/usr/share/nginx/html/LocalSettings.php
       - /media/favrice/mediawiki/images:/usr/share/nginx/html/images
       - /srv/mediawiki/extensions:/usr/share/nginx/html/extensions
       - /srv/mediawiki/conf.d:/etc/nginx/conf.d
     environment:
       - VIRTUAL_HOST=wiki.zbeul.ist
   db:
     image: mysql
     restart: unless-stopped
     network_mode: bridge
     env_file: secrets.env # MYSQL_ROOT_PASSWORD

J'ai mis les mot de passe dans des fichiers séparés "secrets.env".

Donc tous les trucs qui tournent sont trouvables sur le gitlab de chez thomas : [1].

Les liens utiles

Ben franchement bof, la doc de docker et de docker-compose est chiante à utiliser, manque d'exemple, manque de bonne pratiques. C'est du google, de la lecture d'issue github, et tout.