From ef5ffaa782bf98b5b2916fdef2906b60aaa6905d Mon Sep 17 00:00:00 2001 From: nemunaire Date: Wed, 14 Sep 2016 22:51:14 +0200 Subject: [PATCH] Rework TP2 --- tutorial/2/compose.md | 39 +++++++++++++-- tutorial/2/first.md | 96 ++++++++++++++++++------------------- tutorial/2/goodpractices.md | 51 ++++++++++++-------- tutorial/2/installation.md | 3 +- tutorial/2/project.md | 16 +++++-- tutorial/2/supervisor.md | 54 ++++++++++----------- tutorial/2/what.md | 13 ++--- 7 files changed, 160 insertions(+), 112 deletions(-) diff --git a/tutorial/2/compose.md b/tutorial/2/compose.md index 93e8c4f..582f76e 100644 --- a/tutorial/2/compose.md +++ b/tutorial/2/compose.md @@ -7,7 +7,7 @@ bien cette dernière bonne pratique d'un seul processus par conteneur :-( L'intérêt est de permettre à chaque conteneur d'effectuer une tâche -générique, de manière à pouvoir être réutilisé pour d'autres projet +générique, de manière à pouvoir être réutilisé pour d'autres projets dans le futur. Par exemple, notre conteneur InfluxDB pourra être utilisé pour stocker des relevés de métriques systèmes ou des logs. Grafana peut également afficher davantage d'informations ou combiner @@ -22,10 +22,11 @@ nous allons garder la partie InfluxDB, de l'autre la partie Grafana. Il va vous falloir créer deux dossiers distincts, il en faut un par `Dockerfile`. -Profitez en pour rajouter les Data Volume Container. +Profitez en pour rajouter les Data Volume Container, si vous ne l'avez +pas fait dans la partie précédente ! -## Automatiser le lancement +## Automatiser la construction et le lancement Commencez par lancer tous vos conteneurs à la main pour voir les étapes que vous allez devoir automatiser. @@ -34,3 +35,35 @@ Au lieu de faire un script pour construire et lancer tous vos conteneurs, définissez à la racine de votre projet un fichier `docker-compose.yml` qui contiendra les méthodes de construction et les paramètres d'exécution. + +``` +influxdb: + ... +grafana: + build: grafana/ + image: nginx + ports: + - "3000:3000" + volumes: + - ./:/tmp/toto + links: + - influxdb +``` + +Ce fichier est un condensé des options que vous passez habituellement +au `docker run`. + +L'exemple ci-dessus est à adapter largement, consultez + pour une liste exhaustive des +options que vous pouvez utiliser. + + +Une fois que votre `docker-compose.yml` sera prêt, lancez tout d'abord +`docker-compose build` pour commencer la phase de build de tous les +conteneurs listés dans le fichier. + +Une fois le build terminé, vous pouvez lancer la commande suivante pour admirer le résultat : + +``` +docker-compose up +``` diff --git a/tutorial/2/first.md b/tutorial/2/first.md index 36bdbc2..83c48c9 100644 --- a/tutorial/2/first.md +++ b/tutorial/2/first.md @@ -2,82 +2,82 @@ # Premiers pas -Dans un premier temps, nous allons créer une image Docker comme si -l'on réalisait l'installation sur une machine classique : en suivant -une recette. La machine (notre première image Docker) contient tout le -nécessaire pour faire fonctionner notre service. +Dans un premier temps, nous allons créer une image Docker comme si l'on +réalisait l'installation sur une machine classique : en suivant les méthodes +habituelles, mais tout en écrivant notre recette dans le `Dockerfile`. La +machine (notre première image Docker) contiendra tout le nécessaire pour faire +fonctionner notre service. ## Les caches Nous avons vu que chaque instruction de notre `Dockerfile` génère une couche. Chaque couche sert de cache d'une construction de conteneur à -l'autre. Ainsi, lorsque vous modifiez une instruction dans votre -`Dockerfile`, les instructions précédentes ne sont pas réexécutées -mais sont ressorties du cache. +l'autre. Ainsi, lorsque vous modifiez une instruction dans votre `Dockerfile`, +les instructions précédentes ne sont pas réexécutées mais sont ressorties du +cache. -Le cache se basant principalement sur le contenu de chaque instruction -dans le `Dockerfile` (pour les `COPY` et `ADD`, il va aussi regarder -la date de dernière modification de fichier copié ou ajouté). Donc -tant qu'une instruction n'est pas modifiée dans le `Dockerfile`, le -cache sera utilisé. +Le cache se base principalement sur le contenu de chaque instruction dans le +`Dockerfile` (pour les `COPY` et `ADD`, il va aussi regarder la date de +dernière modification de fichier copié ou ajouté). Donc tant qu'une instruction +n'est pas modifiée dans le `Dockerfile`, le cache sera utilisé. -Il est possible de ne pas utiliser le cache et de relancer toutes les -étapes du `Dockerfile` en ajoutant l'option `--no-cache` au moment du -`docker build`. +Il est possible de ne pas utiliser le cache et de relancer toutes les étapes du +`Dockerfile` en ajoutant l'option `--no-cache` au moment du `docker build`. -Les couches du cache peuvent être partagées entre plusieurs conteneur, -c'est ainsi que vous pouvez partager facilement une plus grosse partie -du système de fichier (afin de profiter du cache du système de -fichiers au moment de l'exécution du conteneur). +Les couches du cache peuvent être partagées entre plusieurs conteneur, c'est +ainsi que vous pouvez partager facilement une plus grosse partie du système de +fichiers (afin de profiter du cache du système de fichiers au moment de +l'exécution du conteneur). +\vspace{1.5em} -## `apt-get` +Pour profiter du cache, il faut donc placer les étapes les plus génériques (qui +seraient susceptibles d'apparaître dans plusieurs conteneur), en haut du +`Dockerfile`. -Pour profiter du cache, il faut donc placer les étapes les plus -génériques (qui seraient susceptibles d'apparaître dans plusieurs -conteneur), en haut du `Dockerfile`. - -Commençons donc notre `Dockerfile` : choisissez une image de base pour -votre `FROM`, et indiquez votre nom avec l'instruction `MAINTAINER`, -pour indiquez que c'est vous qui maintenez ce conteneur (si d'autres -gens ont besoin qu'il faut le mettre à jour par exemple). +Commençons donc notre `Dockerfile` : choisissez une image de base pour votre +`FROM`, et indiquez votre nom avec l'instruction `MAINTAINER`, pour indiquez +que c'est vous qui maintenez ce conteneur (si d'autres gens ont besoin qu'il +faut le mettre à jour par exemple). ## `RUN` ou script ? ### InfluxDB -Ensuite viens l'installation d'InfluxDB. Le paquet n'est pas -disponible dans les dépôts. La -[https://influxdb.com/docs/v0.9/introduction/installation.html](procédure -décrite sur le site) incite à télécharger le paquet mis à disposition -puis à l'installer via `dpkg -i`. +Ensuite vient l'installation d'InfluxDB. Le paquet n'est pas disponible dans +les dépôts. La +[procédure décrite sur le site](https://influxdb.com/docs/v0.9/introduction/installation.html) +incite à télécharger le paquet mis à disposition puis à l'installer via `dpkg +-i`. -Deux solutions s'offrent à nous : télécharger le paquet hors du -conteneur, le copier, puis l'installer. Ou faire un `RUN` avec toutes -ces opérations (sans oublier l'installation de `wget`/`curl`). +Deux solutions s'offrent à nous : télécharger le paquet hors du conteneur, le +copier, puis l'installer. Ou faire un `RUN` avec toutes ces opérations (sans +oublier l'installation de `wget`/`curl`). -La copie étant définitive (supprimer le fichier ne le supprimera pas -des couches où il a pu exister), donc la seconde solution semble -préférable (mais `wget` restera en déchet). +La copie étant définitive (supprimer le fichier ne le supprimera pas des +couches où il a pu exister), donc la seconde solution semble préférable (mais +`wget` restera en déchet). -Écrivez une commande `RUN` qui va télécharger la dernière version -d'InfluxDB, qui va l'installer et supprimer le fichier. +Écrivez une commande `RUN` qui va télécharger la dernière version d'InfluxDB, +qui va l'installer et supprimer le fichier. \vspace{1em} -À ce stade, nous pouvons déjà terminer le conteneur et tester -qu'InfluxDB est bien utilisable : `EXPOSE`, `CMD`, ... Il est possible -que vous ayez à écraser le fichier de configuration via un -`COPY`. Garder la ligne qui vous permet de lancer votre serveur web -dans un coin, en attendant la partie suivante. +À ce stade, nous pouvons déjà terminer le conteneur et tester qu'InfluxDB est +bien utilisable : `EXPOSE`, `CMD`, ... + +Il est possible que vous ayez à écraser le fichier de configuration via un +`COPY` (ou de manière plus maline en utilisant `--volume` au moment du `docker +run`, cela fonctionne pas qu'avec les dossiers). Garder la ligne qui vous +permet de lancer votre serveur web dans un coin, en attendant la partie +suivante. ### Grafana -Une fois InfluxDB configuré, nous allons avoir la même réflexion avec -Grafana. +Une fois InfluxDB configuré, nous allons avoir la même réflexion avec Grafana. De la même manière, téléchargez, installez et supprimez le paquet. diff --git a/tutorial/2/goodpractices.md b/tutorial/2/goodpractices.md index ba7194c..cf6e1a1 100644 --- a/tutorial/2/goodpractices.md +++ b/tutorial/2/goodpractices.md @@ -2,7 +2,8 @@ # Retour sur les bonnes pratiques -http://docs.docker.com/articles/dockerfile_best-practices/ +Pour chacune des bonnes pratiques ci-dessous, vérifiez que vous les respectez +bien, faites les modifications nécessaires. ## Utilisez le fichier `.dockerignore` @@ -105,7 +106,7 @@ Il y a un certain nombre de règles à connaître pour bien utiliser ce mécanis ## Concevez des conteneur éphémères Les conteneurs que vous générez doivent aussi éphémères que possible : ils -devraient pouvoir être arrêtés, détruits et recréés sans nécessité d'étape de +devraient pouvoir être arrêtés, détruits et recréés sans nécessiter d'étape de reconfiguration. La configuration devrait se faire au lancement du conteneur ou lors de sa construction. @@ -149,32 +150,32 @@ L'entrypoint peut être utilisé de deux manières différentes : après le nom de l'image, corresponde aux arguments attendu par le programme indiqué dans l'entrypoint. Par exemple pour nginx : - ``` - ENTRYPOINT ["nginx"] - CMD ["-g daemon off;"] - ``` +``` +ENTRYPOINT ["nginx"] +CMD ["-g daemon off;"] +``` - Vous pouvez aussi utiliser un script qui servira à faire les initialisations ou les configurations nécessaire au bon fonctionnement du conteneur (rappelez-vous, il doit être éphémère !). Par exemple, le `Dockerfile` pour l'image de PostgreSQL possède cet entrypoint : - ``` - #!/bin/bash - set -e +``` +#!/bin/bash +set -e - if [ "$1" = 'postgres' ]; then - chown -R postgres "$PGDATA" +if [ "$1" = 'postgres' ]; then +chown -R postgres "$PGDATA" - if [ -z "$(ls -A "$PGDATA")" ]; then - gosu postgres initdb - fi +if [ -z "$(ls -A "$PGDATA")" ]; then + gosu postgres initdb +fi - exec gosu postgres "$@" - fi +exec gosu postgres "$@" +fi - exec "$@" - ``` +exec "$@" +``` ## `[""]`, `'` et sans `[]` @@ -194,7 +195,7 @@ pouvez pas utiliser les simple quotes. ## Volumes L'instruction `VOLUME` doit être utilisée pour exposer tous les espaces de -stockage +stockage de données, configuration, ... ## Réduisez les privilèges @@ -205,6 +206,18 @@ réclame pas de privilège particulier. Il vous faudra sans doute créer l'utilisateur et son groupe dans le Dockerfile. +## Profitez du système de liaison et de résolution de nom + +Dès lors que vous effectuez un lien avec un autre conteneur, son nom (ou son +alias) est ajouté au fichier `/etc/hosts`. Cela signifie que lorsqu'un nom de +domaine correspondant au nom du conteneur (ou son alias) sera recherché, l'IP +sera bien celle du conteneur. Lorsque vous configurez un conteneur, utilisez de +préférence un nom plutôt qu'une IP, qui changera à coup sûr. + +Au moment du `docker run`, vous pouvez préciser d'autres noms d'ĥôtes +particuliers en utilisant l'option `--add-host`. + + ## Exécutez un seul processus par conteneur Dans la majorité des cas, vous ne devriez jamais lancer plus d'un seul diff --git a/tutorial/2/installation.md b/tutorial/2/installation.md index 9656375..81f9d06 100644 --- a/tutorial/2/installation.md +++ b/tutorial/2/installation.md @@ -8,7 +8,8 @@ L'équipe en charge de Docker compose met à disposition un binaire contenant tous les scripts. Nous pouvons l'installer en suivant la procédure suivante : ``` -curl -L https://github.com/docker/compose/releases/download/1.3.3/docker-compose-Linux-x86_64 > /usr/bin/docker-compose +curl -L https://github.com/docker/compose/releases/download/1.3.3/docker-compose-Linux-x86_64 \ + > /usr/bin/docker-compose chmod +x /usr/bin/docker-compose ``` diff --git a/tutorial/2/project.md b/tutorial/2/project.md index acce53b..e91ab97 100644 --- a/tutorial/2/project.md +++ b/tutorial/2/project.md @@ -2,6 +2,16 @@ # Rendu +## Avis + +Dans le courriel que vous enverrez, je serais ravi de connaître votre avis sur +ce cours : aussi bien les choses que vous avez apprécié que celles que vous +n'avez pas aimés. + +Cela ne rentrera pas en compte dans la notation, mais permettra d'améliorer ce +cours. + + ## TP Rendez le contenu de votre dossier à la dernière étape du TP : avec le @@ -13,9 +23,9 @@ annexes. De la même manière que nous avons réaliser un groupe de conteneurs utilisant `grafana` et `InfluxDB`, qui permet d'afficher facilement des métriques sous -forme de graphiques, vous allez réaliser, à l'aide des images Docker -présentent sur le hub, une interface web de recherche et de visualisation de -logs, utilisant +forme de graphiques, vous allez réaliser, à l'aide des images Docker présentent +sur le hub, une interface web de recherche et de visualisation de logs, +utilisant [Kibana](https://www.digitalocean.com/community/tutorials/how-to-install-elasticsearch-logstash-and-kibana-4-on-ubuntu-14-04). Toutes la chaîne d'image Docker est déjà présente sur le hub : diff --git a/tutorial/2/supervisor.md b/tutorial/2/supervisor.md index 7dbbb30..2dc13bc 100644 --- a/tutorial/2/supervisor.md +++ b/tutorial/2/supervisor.md @@ -4,21 +4,21 @@ ## Script d'init -Lors du dernier TP, nous avons vu que les conteneurs étaient détruits -dès que le premier processus du conteneur (celui qui a le PID 1, à la -place d'`init`) terminer son exécution, quelque soit le statut de ses -éventuels fils. +Lors du dernier TP, nous avons vu que les conteneurs étaient détruits dès que +le premier processus du conteneur (celui qui a le PID 1, à la place d'`init`) +terminer son exécution, quelque soit le statut de ses éventuels fils. -Pour lancer tous nos daemon, +Pour lancer tous nos daemon, nous allons donc besoin d'écrire un script qui +lance puis attend que les deux deamons aient terminés de s'exécuter ## Autorestart -L'avantage de détruire le conteneur à la mort du père, est que s'il -s'agit de notre processus principal et qu'il est seul (par exemple -`nginx` pour un conteneur qui délivre des pages web), il va être -possible de redémarrer le conteneur automatiquement grâce à la -*restart policy* que l'on peut définir au moment du `docker run` : +L'avantage de détruire le conteneur à la mort du père, est que s'il s'agit de +notre processus principal et qu'il est seul (par exemple `nginx` pour un +conteneur qui délivre des pages web), il va être possible de redémarrer le +conteneur automatiquement grâce à la *restart policy* que l'on peut définir au +moment du `docker run` : ``` docker run -d -p 80:80 --restart=on-failure nginx @@ -26,28 +26,26 @@ docker run -d -p 80:80 --restart=on-failure nginx Il existe trois règles de redémarrage différentes : -- **`no` :** il s'agit de la règle par défaut. Lorsque l'exécution du - conteneur se termine, il n'est pas redémarré. -- **`on-failure[:max-retries]` :** redémarre uniquement si le code de - sortie du conteneur n'est pas 0. Il est possible de préciser pour - cette option le nombre maximum de redémarrage qui sera tenté. -- **`always` :** redémarre le conteneur dans tous les cas, quelque - soit son code de sortie et indéfiniment. +- **`no` :** il s'agit de la règle par défaut. Lorsque l'exécution du conteneur + se termine, il n'est pas redémarré. +- **`on-failure[:max-retries]` :** redémarre uniquement si le code de sortie du + conteneur n'est pas 0. Il est possible de préciser pour cette option le + nombre maximum de redémarrage qui sera tenté. +- **`always` :** redémarre le conteneur dans tous les cas, quelque soit son + code de sortie et indéfiniment. -Le script d'init que vous avez réalisé ne tient sans doute pas compte -de cela. Mais plein de gens ont cette problématique et `supervisor` +Le script d'init que vous avez réalisé ne tient sans doute pas compte de +cela. Mais plein de gens ont cette problématique et l'application `supervisor` répond parfaitement à notre problématique ! ## `supervisor` -Première étape : installer `supervisor`, le paquet se trouve dans les -dépôts. +Première étape : installer `supervisor`, le paquet se trouve dans les dépôts. -L'étape suivante consiste à remplir puis copier le fichier de -configuration dans le conteneur. Vous allez devoir écraser dans votre -conteneur le fichier `/etc/supervisord.conf` pour démarrer à la fois -`grafana` et `influxdb`. +L'étape suivante consiste à remplir puis copier le fichier de configuration +dans le conteneur. Vous allez devoir écraser dans votre conteneur le fichier +`/etc/supervisord.conf` pour démarrer à la fois `grafana` et `influxdb`. Vous pouvez vous aider de la documentation disponible à : @@ -55,6 +53,6 @@ Vous pouvez vous aider de la documentation disponible à : ## C'est parti ! -Votre conteneur doit maintenant être parfaitement fonctionnel : vous -devriez pouvoir lancer votre script de monitoring et voir apparaître -vos données dans Grafana ! +Votre conteneur doit maintenant être parfaitement fonctionnel : vous devriez +pouvoir lancer votre script de monitoring et voir apparaître vos données dans +Grafana ! diff --git a/tutorial/2/what.md b/tutorial/2/what.md index eb201f6..628e55a 100644 --- a/tutorial/2/what.md +++ b/tutorial/2/what.md @@ -1,5 +1,3 @@ -\newpage - # But du TP Aujourd'hui, nous allons terminer notre système de monitoring commencé lors du @@ -8,11 +6,6 @@ premier TP. Le résultat attendu d'ici la fin du TP, est un groupe de conteneurs indépendants les uns des autres, réutilisables en fonction des besoins. -TODO image de graphana - -Nous reprendrons le script de monitoring que vous avez rendu au premier TP. Les -données collectées seront envoyés vers [https://influxdb.com/](InfluxDB), puis -elles seront affichées sous forme de graphique dans -[http://grafana.org/](Grafana). L'interface sera servie par un reverse-proxy -qui vous permettra de n'ouvrir que le port 80 ou 443, pour accéder à -l'interface d'administration d'InfluxDB et à l'interface de Grafana. +Les données collectées seront envoyés vers +[InfluxDB](https://influxdb.com/), puis elles seront affichées sous +forme de graphique dans [Grafana](http://grafana.org/).