cloud:2016:tp_docker

Utilisation de Docker

En plus de la machine virtuelle nous allons utiliser docker pour séparer les différententes applications. Le but de ce TP est d'installer 4 conteneurs :

  1. un docker nginx en tant que proxy inverse, il assurera la répartition des requêtes http sur les différents conteneurs;
  2. deux dockers apache pour avoir un premier site web/php et de l'équilibrage de charge entre les deux.
  3. un docker mysql pour stocker les données du site web.

Vous devez créer une machine virtuelle, mais cette fois sans utiliser de volume. Créez une instance :

  • avec la flavor xsmall
  • choisissez la source boot from image
  • et l'image ubuntu 16.04

Vous devez installer docker sur votre VM, il y a 2 version de docker utilisable sur ubuntu : docker.io un paquet directement instalable via apt-get et docker-engine qui demande de suivre une procédure décrite ici. docker-engine contient en plus de docker les utilitaire pour faire de l'orchestration que vous utiliserez dans les TPs suivants.

  • Installez docker-engine.

Docker n'est pas encore fonctionnel dans cet environnement, car il a besoin d'accéder au réseau et il faut le configurer pour utiliser le proxy de l'université. Cette configuration n'est pas simple car elle doit modifier le service docker de la machine et dépend donc du gestionnaire de service. Elle n'est nécessaire que dans des réseaux utilisant un proxy comme celui des machines virtuelles de notre université. Elle n'est pas nécessaire si docker est installé sur une machine ayant directement accès au réseau (comme votre PC). La configuration est expliquée ici. Vous pouvez suivres bêtement les instructions suivantes (qui ne seront pas expliquées car hors du champ de ce TP).

  • Créez un répertoire pour stocker les configurations du service docker
mkdir -p /etc/systemd/system/docker.service.d
  • Créez un fichier de configuration /etc/systemd/system/docker.service.d/http-proxy.conf contenant :
[Service]
Environment="HTTP_PROXY=http://proxy.univ-lyon1.fr:3128/"
  • relancer le gestionnaire de service
systemctl daemon-reload
  • Vérifier que la modification est prise en compte
systemctl show docker
# la liste des options doit contenir un élément Environment="HTTP_PROXY=http://proxy.univ-lyon1.fr:3128/"
  • Relancer le service docker
systemctl restart docker
  • Vous pouvez normalement utiliser docker par exemple en recherchant un docker contenant un serveur sql:
docker search mysql

Comme pour beaucoup de serveurs connus, il existe un docker officiel qui permet l'installation de nginx très simplement. Pour cela vous allez simplement télécharger l’image et créer un docker dont le répertoire de configuration sera partagé avec l’hôte. Dans votre rapport, vous noterez chaque commande faite pour effectuer les installations et configurations.

  • Recherchez la list des dockers fournissant nginx, (commande docker search) vous verrez qu'ils sont classés par défaut grâce à un système de recommandation via des étoiles.
  • Recherchez de la même manière sur le site docker hub. Ce site donne plus de détails notamment les différentes versions pour une image, les Dockerfile
    • Comment reconnait-on la dernière version ?
    • Quels sont les différences entre la version stable et la dernière version alpine-stable ? <hi #f3f3f3>Regardez les Dockerfiles</hi>
  • Téléchargez l'image de la dernière version stable (docker pull …)
  • Vérifiez que l'image est bien téléchargée, son nom et son tag.
  • Lancez un premier docker basé sur cette image dont le nom est test, dont le hostname est test et faites en sorte que la machine virtuelle renvoie le port 80 et le port 443 sur ce docker (commandes docker run -d … ou docker create puis docker start)
  • Testez si le docker fonctionne et répond sur le port 80 de la VM
  • Exécutez un shell bash dans le docker (commande docker exec -it …) et créer un fichier à la racine /toto à la racine du docker contenant coucou.
  • Sortez du docker et essayer de retrouver le fichier sur la VM. Pour cela,
    • Avec docker.io vous pouvez utiliser docker inspect pour voir où sont stockées les données du docker. Je vous recommande de vérifier le contenu des variables : LowerDir, MergedDir, UpperDir et WorkDir. Comparez ces 3 répertoires et essayez de comprendre d'où vienne l'essentiel des fichiers du docker, où se trouve les modifications et dans quel répertoire sont exécuté les processus du docker.
    • Avec docker-engine vous pouver rechercher le fichier toto dans le système de fichier des docker :

find /var/lib/docker/ -name “toto”

Vous avez peut-être remarqué que les outils les plus courants (nano, vim, emacs …) ne font pas parti du docker nginx ce qui rend difficile la modification des fichiers dans le docker. Pour résoudre le problème, on peut :

  1. Pré-configurer le docker via le Dockerfile ou les outils de création (voir plus tard);
  2. Installer dans le docker votre éditeur préféré;
  3. Copier des fichiers entre la VM et le docker;
  4. Partager des répertoires entre la VM et le docker.

Nous allons utiliser la dernière méthode dans ce cas pour gérer les configurations de nginx qui sont dans le répertoire /etc/nginx du docker, mais pour cela il faut recréer un docker.

  • Copiez le répertoire /etc/nginx du docker test dans le répertoire /docker/nginx/config de la VM (commande docker cp …)
  • Supprimez le docker test(commande docker rm …)
  • Recréez un docker dont le nom est nginx, le hostname est nginx, qui partage les mêmes ports que le précédant et dont le répertoire /etc/nginx correspond au répertoire /docker/nginx/config/ de la VM.
  • Pour vérifier que cela fonctionne bien, modifiez la configuration des logs de nginx depuis la VM (fichier /docker/nginx/config/nginx.conf), relancer le docker (docker restart …), afficher les logs dynamiquement (commande docker logs -f nginx) et générer un log en utilisant le navigateur pour demander une page inexistante.

Si vous avez des problèmes de fonctionnement, testez :

  1. les logs du docker avec la commande docker logs nomdocker
  2. le contenu des fichiers utilisés par le docker (surtout s'il s'agit de fichier partagés car beaucoup d'erreurs sont faites durant le partage).

Vous trouverez ici une explication de l'erreur la plus courante.

Lorsque tout fonctionne, vous pouvez passer à la section suivante.

Il existe des dockers apache tout fait, mais il sont basés sur des versions minimalistes et il est alors difficile de rajouter des modules. Vous allez donc utiliser un docker ubuntu (vivid). Pour cela vous allez utiliser une seconde façon de créer une image docker, le faire à partir d’un Dockerfile. Un Dockerfile est un fichier décrivant à partir d’une image de base la suites des actions à réaliser pour créer une nouvelle image ainsi que l’environnement dans lequel sera exécuté le conteneur. A partir du fichier Dockerfile fourni, vous allez écrire un nouveau fichier pour construire une image qui contient apache et le lance par défaut avec les modules php-pear , php5-ldap, php-auth, php5-mysql et php5-common.

  • Construisez une première image (nommée ubuntuapache:v0) sans modifier le fichier, vous pourrez utiliser cette image pour tester les commandes.
  • Modifiez le fichier Dockerfile
    • pour installer les modules nécessaires;
    • pour modifier le nom du serveur web pour apache (via la commande sed) 1);
    • pour activer l'affichage des erreurs php voir ici pour une explication de la raison et de la commande sed à faire dans le docker.
  • Lancez un docker dont le répertoire principale d’apache /var/www/html/ est partagé avec l’hôte /docker/apache/html/. Ne faites pas de partage de port.
  • Quel est l'adresse de ce docker ? (via la commande docker inspect …')
  • Testez le fonctionnement du serveur. Attention, ce dernier ne peux pas être contacté directement depuis votre PC car le réseau des machines virtuelle est derrière un firewall, vous devez donc utiliser un tunel ssh, ou un client locale à la VM comme telnet 2).
  • Configurez nginx pour que le chemin /site soit envoyé sur le serveur apache en utilisant le proxy_pass du serveur nginx et l'adresse IP du docker apache.
  • Testez le site avec un fichier php contenant :
<?php
phpinfo();
?>
  • phpinfo affiche entre autre les variables du serveur (tableau $_SERVER). Quel est l'adresse du serveur ? Le chemin utilisé ? L'adresse du client ?

<hi #99d9ea>Vous devez rendre un rapport expliquant votre travail durant ce TP avant mardi 1/11/16 23h42 UTC. Pour chaque questions, votre rapport doit mentionner les commandes utilisées pour faire les configurations, les fichiers modifiés et les résultats obtenus. </hi>

Comme vous l'avez vu, il est possible d'utiliser les adresses IP attribuées par le service docker pour configurer les liaisons entre ces derniers, mais ces adresses peuvent changer. Cela peut poser des problèmes par exemple lorsque vous devez réutiliser un docker préparé dans un certains contexte. Pour simplifier la gestion, il est possible de choisir les adresses IP des dockers, de choisir la valeur de leurs variables d'environnement ou de paramétrer leur fichier /etc/hosts.

  • Vous devez tout d'abord créer un réseau utilisateur via la commande docker network create …. Attention, il faut utiliser l'option subnet pour définir le réseau. Créer un réseau de nom interne et utilisant le reseau 172.18.100.0/24.
  • Supprimez le docker apache puis recréez 2 nouveaux dockers utilisant le réseau interne (option –network ou –net selon la version de docker) et en attribuant 2 adresses (option - -ip) :
    • un docker appelé apache1 utilisant l'adresse 172.18.100.10;
    • un docker appelé apache0 utilisant l'adresse 172.18.100.11;

Ces 2 dockers doivent partager le volume /var/www/html/ sur le repertoire /docker/apache/html de l'hôte.

  • Supprimez le docker nginx puis recréez le en ajoutant à son fichier hosts les dockers apache avec leurs adresses (option –add-host).
  • Ajoutez nginx au réseau interne (commande docker network connect …).
  • Verifiez que nginx puisse contacter les deux dockers apache (avec un ping). La VM peut-elle contacter ces dockers ? Une autre VM le peut-elle ?
  • Vous devriez pouvoir configurer le docker pour utiliser le serveur http://apache1/ afin d'envoyer les requètes pour l'adresse /site1 (respectivement http://apache2/ pour /site2).

Cette série de questions n'a pas vraiment de rapport avec le TP mais vous donnera les bases pour travailler vos TPs depuis chez vous. Pour être en conditions réelles, si vous en avez la possibilité (et pour cette série uniquement) utilisez un partage de connexion de votre téléphone.

Pour travailler vous devez pouvoir :

  1. contacter une page web interne comme http://cloud-info.univ-lyon1.fr;
  2. vous connecter sur des machines distantes pour exécuter des programmes;
  3. vous connecter à des serveurs distants protégés par le firewall de l'université (oracle, serveur ssh des VM, …).

Utilisation du "vpn" proposé aux étudiants

Ce n'est pas vraiment un vpn, mais un simple site avec des applications en javascript pour faire des connexions de base. Je ne pense pas qu'il permettra de tout faire, mais il vaut mieux le connaître. Il est à l'adresse https://vpn.univ-lyon1.fr/. * utilisez-le pour ouvrir le site web de votre VM. * utilisez le pour ouvrir une session ssh sur votre VM. Cette partie supposait que le VPN des étudiants contient des services utiles, ce qui ne semble pas le cas.

Utilisation d'un tunnel ssh

Tous ce que vous voulez faire peut être fait grâce à des tunnels ssh. C'est donc une technique à maitriser même si ce n'est pas la plus pratique. Voir ici une explication de ce qu'est un tunnel et comment ils se mettent en place (voir aussi ). Pour vous connectez de l'extérieur, vous pouvez utiliser la machine linux linuxetu.univ-lyon1.fr qui est une simple passerelle.

  • Utilisez linuxetu pour vous connecter à l'université.
  • Utilisez 2 connexions ssh de votre machine sur linuxetu puis de linuxetu sur votre VM. Attention, pour se connecter à la VM il faut utiliser une clef ssh, or cette clef n'est pas sur linuxetu. Il faut donc utiliser l'agent ssh et la capacité de transférer l'agent via une connexion. Commande ssh-add pour ajouter une clef à l'agent et option -A lors de la connexion à ssh pour transférer l'agent.
  • Mettez en place un tunnel de votre machine de travail vers linuxetu entre le port local 19222 et le port ssh de votre VM. Il doit vous permettre d'ouvrir plusieurs connexions ssh de votre machine de travail vers votre VM directement. Dans votre rapport, en plus de la commande pour ouvrir le tunnel et tester les connexions, dites bien à quoi correspondent les valeurs des options et lesquelles doivent correspondre entre elles.
  • Utilisez de plus ce tunnel pour copier un petit fichier de votre machine de travail vers la VM. Attention, scp est assez sensible, il faut que l'option du port utilisé -P soit placée juste après la commande scp, il est aussi possible d'utilsier des outil graphique pour la copie (voir le premier TP).

Cela ne permet pas d'aller sur des pages web facilement, mais vous pouvez utiliser un proxy en plus d'un tunnel pour naviguer sur internet en passant par le réseau de l'université.

  • Mettez en place un tunnel entre votre machine et le serveur proxy.univ-lyon1.fr port 3128. Configurez votre navigateur pour utiliser le proxy via le tunnel. Dans votre rapport mettez bien la commande pour mettre en place le proxy et les configurations du navigateur.

<hi #ed1c24>Attention</hi>, il faut penser à supprimer la configuration du proxy lorsque vous supprimer le tunnel ou que vous changer de réseau. Sinon, votre navigateur ne fonctionne plus.

[Si vous êtes en avance] Utilisation d'un tunnel dynamique et d'un proxyfieur

La méthode précédente permet de faire a peut près tous, mais elle est parfois laborieuse. En effet, il faut un tunnel par application et il faut modifier les configurations des logiciels clients. L'utilisation du proxy est plus souple, mais elle est limitée aux protocoles du web car en général les proxy ne laissent passer que ce type de flux. Ssh permet aussi de mettre en place des tunnels dynamiques socks5 c'est à dire un proxy au niveau de la connexion TCP. Grâce à ce type de tunnels on peut utiliser la connexion ssh pour transporter n'importe quoi. Pour que cela fonctionne, il faut que le logiciel client soit capable de faire l'opération de discussion avec le proxy socks. C'est pour cela qu'on a besoin d'un proxyfieur c'est à dire un logiciel qui permet de transformer n'importe quelle application en client d'un proxy socks. Ici nous allons utiliser proxychains4

  • Sur votre machine de travail installez proxychains4
  • sur le fichier /etc/proxychains.conf remplacer le point d'entrée du proxy
# defaults set to "tor"
socks4         127.0.0.1 9050
  par le point d'entrée d'un tunnel dynamique ssh (ici j'utilise 9022 ce qui est totalement arbitraire).
  
socks5  127.0.0.1 9022 
  • Créer ce tunnel avec l'option -D de ssh
ssh -D 9022 p???????@linuxetu.univ-lyon1.fr

A partir de ce moment, une application lancée précédée de la commande proxychains4 utilise le proxy. Les autres ne l'utilisent pas. Par exemple :

> proxychains4 scp toto.gz ubuntu@192.168.246.87: 
# copie le fichier local toto.gz sur le compte ubuntu du serveur 192.168.246.87 accessible
# depuis linuxetu (c'est sans doute une VM) elle passe par le tunnel et fonctionne depuis n'importe quel endroit.
> scp toto.gz ubuntu@192.168.246.87:
# copie le même fichier sur le compte ubuntu du serveur 192.168.246.87 accessible
# depuis la machine où vous travaillez (ce qui ne fonctionnera sans doute pas chez vous).

Nous allons configurer nginx pour répartir des requêtes sur les 2 dockers apache. La documentation de l'équilibrage de charge de nginx est ici

  • En modifiant la configuration de votre docker nginx (fichiers nginx:/etc/nginx/conf.d/default.conf et nginx:/etc/nginx/nginx.conf) renvoyez les requêtes vers la racine du site / sur les deux dockers apache1 et apache2 en alternant le serveur effectivement contacté. <hi #ed1c24>Attention</hi>, la partie upstream doit allez dans le fichier nginx.conf, la partie location dans default.conf.
  • Testez la répartition de charge en ajoutant dans les deux serveurs apache le fichier test.php contenant :
<?php
echo "<pre>".print_r($_SERVER, true)."</pre>";
?>
  • Quelle(s) variable(s) permet(tent) de savoir le docker qui est finalement contacté ?

Dans votre rapport vous joindrez le fichier nginx:/etc/nginx/conf.d/default.conf et nginx:/etc/nginx/nginx.conf

Vous devez installer une petite application tiny. C'est un mini framework en php. Il utilise une base de donnée mysql (que vous mettrez, bien sûr, dans un docker à part).

  • Récupérez le zip du projet sur votre VM https://github.com/panique/tiny ou ici et installez le dans le répertoire des serveurs apache. Le projet doit faire une erreur lors de la connexion à la base de donnée car cette dernière n'existe pas encore.
  • Télécharger l'image mysql (la dernière) et lancer un docker qui :
    • est dans le réseau interne
    • utilise l'adresse 172.18.100.3
    • s'appelle mysql (nom du docker et hostname)
    • utilise votre numéro étudiant comme mot de passe root (regarder sur la description du docker mysql dans le docker hub pour apprendre comment on fait)
  • Recréez les dockers apache1 et apache2 pour qu'ils connaissent l'adresse de la base de donnée sous le nom mysql en utilisant l'option –add-host à la création (n'oubliez pas de les relancer). Modifiez le fichier de configuration tiny/application/config/config.php pour lui donner les bonnes valeurs pour la base de données.
  • Vous devez remplir la base de données grâce au 3 scripts qui sont dans le répertoire _installation du projet. Pour cela il faut utiliser la commande (exécutez cette commande sur la VM après avoir installé le paquet mysql-client) :
mysql -u root -p -h adr_ip_de_mysql < nom_du_fichier_script.sql 
  • Testez le site :
    • Si vous obtenez une erreur 403 forbidden you don't have permission to access /tiny-master/ on this server allez ici pour une explication.
    • Si vous obtenez une page vide allez ici pour une explication.
    • Si vous obtenez une page qui commence par Everything in this box is loaded from application/views/_templates/header.php ! passez à la question suivante.
  • Le site ne fonctionne pas vraiment. En fait toutes les urls sont fausses car elles utilisent l'adresse du docker et non pas celles du site. Cela est dû à l'utilisation de la variable $_SERVER['HTTP_HOST'] dans la construction de l'url du domain3). Pour corriger le problème, il faut demander à nginx de modifier cette valeur pour qu'elle soit exacte. Pour cela utiliser les options proxy_set_header expliquées ici.

Le site doit être [un peu] plus joli, et surtout les urls doivent fonctionner. Testez l'application song en ajoutant une chanson. Cela doit fonctionner malgré l'équilibrage de charge.

  • Dessinez le shema de fonctionnement final du service, mentionnant la VM et les 4 dockers (où arrivent les requètes de l'extérieur, qui est connecté avec qui …).
  • Pourquoi n'utilise-t-on qu'un seul docker mysql ? Que faudrait-il faire pour en utiliser plusieurs avec de l'équilibrage de charge ?

1)
il y a un exemple de fonctionnement de sed dans le Dockerfile, il faut modifier la ligne #ServerName .* dans le fichier /etc/apache2/sites-enabled/000-default.conf
2)
pour tester un site web avec telnet, il faut taper la commande telnet adresse_du_site 80 puis une fois la connexion étable taper GET /
3)
comme vous pouvez le voir au début du fichier tiny/application/config/config.php
  • cloud/2016/tp_docker.txt
  • Dernière modification : 2017/10/13 12:51
  • de 46.193.0.129