====== 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 : - un docker ''nginx'' en tant que proxy inverse, il assurera la répartition des requêtes http sur les différents conteneurs; - deux dockers ''apache'' pour avoir un premier site web/php et de l'équilibrage de charge entre les deux. - un docker mysql pour stocker les données du site web. =====Création de l'instance de travail===== 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 ====I. Installation de docker==== 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 [[https://docs.docker.com/engine/installation/|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 [[https://docs.docker.com/v1.11/engine/admin/systemd/#custom-docker-daemon-options|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 ====II. Installation d'un docker nginx==== 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// ? Regardez les Dockerfiles * 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 : - Pré-configurer le docker via le ''Dockerfile'' ou les outils de création (voir plus tard); - Installer dans le docker votre éditeur préféré; - Copier des fichiers entre la VM et le docker; - 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 : - les //logs// du docker avec la commande ''docker logs nomdocker'' - 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 [[http://perso.univ-lyon1.fr/fabien.rico/site/cloud:tp_cloud_faq#avec_le_partage_le_docker_nginx_ne_demarre_pas|ici]] une explication de l'erreur la plus courante. Lorsque tout fonctionne, vous pouvez passer à la section suivante. ====III. Installation d'un docker apache==== 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 {{ :cloud:dockerfile_apache-tp2.txt |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'') ((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'')); * pour activer l'affichage des erreurs //php// [[http://perso.univ-lyon1.fr/fabien.rico/site/cloud:tp_cloud_faq#l_application_tiny-master_affiche_une_page_vide|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'' ((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 /'')). * 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 : * ''phpinfo'' affiche entre autre les variables du serveur (tableau ''$_SERVER''). Quel est l'adresse du serveur ? Le chemin utilisé ? L'adresse du client ? ====IV. Utilisation du réseau==== 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. 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''). ==== V. Comment travailler depuis chez vous ? ==== 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 : - contacter une page web interne comme [[http://cloud-info.univ-lyon1.fr]]; - vous connecter sur des machines distantes pour exécuter des programmes; - 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 [[https://openclassrooms.com/courses/mise-en-place-d-un-tunnel-tcp-ip-via-ssh|une explication de ce qu'est un tunnel]] et comment ils se mettent en place (voir aussi [[http://blog.netapsys.fr/creer-des-tunnels-ssh/|là]]). 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. Attention, **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). ====VI. Equilibrage de charge ==== Nous allons configurer ''nginx'' pour répartir des requêtes sur les 2 dockers apache. La documentation de l'équilibrage de charge de nginx [[http://nginx.org/en/docs/http/load_balancing.html|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é. Attention, 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 : ".print_r($_SERVER, true).""; ?> * 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'' ====VII. Installation d'une application==== 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 {{ cloud:2016:master.zip |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 [[cloud:tp_cloud_faq#erreur_403_forbidden_pour_tini-master|ici]] pour une explication. * Si vous obtenez une page vide allez [[http://perso.univ-lyon1.fr/fabien.rico/site/cloud:tp_cloud_faq#l_application_tiny-master_affiche_une_page_vide|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 domain((comme vous pouvez le voir au début du fichier ''tiny/application/config/config.php'')). 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 [[https://www.nginx.com/resources/admin-guide/reverse-proxy/#headers|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 ?