Split Docker tutorials into basis, orchestration and dockerfiles

This commit is contained in:
nemunaire 2017-10-15 22:49:27 +02:00
parent 2d364556a2
commit 2c48fa7942
36 changed files with 477 additions and 188 deletions

View file

@ -1,22 +0,0 @@
SOURCES = tutorial.md installation.md what.md first.md supervisor.md goodpractices.md compose.md project.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=french \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
--include-in-header=../header.tex
all: tutorial.pdf
tutorial.pdf: ${SOURCES}
pandoc ${PANDOCOPTS} -o $@ $+
clean::
rm tutorial.pdf

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View file

@ -1,205 +0,0 @@
\newpage
# Compose
Avec notre conteneur utilisant `supervisor`, nous ne respectons pas
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
simple et 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 d'autres systèmes
ou des logs. Chronograf peut être connecté à d'autres serveurs afin
de corréler les métriques, ...
## Séparer le `Dockerfile`
Commençons par séparer notre `Dockerfile` en deux : dans une partie
nous allons garder la partie InfluxDB, de l'autre la partie Chronograf.
Il va vous falloir créer deux dossiers distincts, il en faut un par
`Dockerfile` : réutilisez l'image `influxdb` créée précédemment et créez le
dossier pour l'image `chronograf`.
\vspace{1em}
Pour tester la bonne marche de vos conteneurs, vous pouvez le lancer votre
conteneur chronograf avec la commande suivante (en considérant que votre
conteneur influxdb de la première partie est toujours lancé).
```shell
docker run --rm --link YOUR_INFLUX_CNTR_NAME:influxdb chronograf
```
Remplacez `YOUR_INFLUX_CNTR_NAME` par le nom du conteneur qui fait tourner
votre influxdb. En créant ce lien, `chronograf` sera capable de contacter une
machine nommée `influxdb` (indiqué par la partie du lien après les `:`).
### Visualiser les données dans `chronograf`
Avant d'arrêter `telegraf` et nos conteneurs pour passer à une nouvelle étape,
prenez le temps d'afficher les données que vous avez collecté depuis le début
du TP.
Après avoir ajouté le serveur (en remplaçant `localhost` proposé par défaut par
`influxdb` issue du *link*), ajouter deux visualisations avec les requêtes
suivantes :
```sql
SELECT used, available, cached FROM mem WHERE tmpltime()
SELECT mean(usage_idle) FROM cpu WHERE tmpltime() GROUP BY time(20s), cpu
```
## Automatiser la construction et le lancement
Commencez par lancer tous vos conteneurs à la main pour voir les
étapes que vous allez devoir automatiser.
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.
```yaml
version: '2'
services:
influxdb:
...
chronograf:
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`.
### `version`
Notez toutefois la présence d'une ligne `version` ; il ne s'agit pas de la
version de vos conteneurs, mais de la version du format de fichier
docker-compose qui sera utilisé. Sans indication de version, la version
originale sera utilisée.
### `services`
Cette section énumère la liste des services (ou conteneurs) qui seront gérés
par `docker-compose`.
Il peuvent dépendre d'une image à construire localement, dans ce cas ils auront
un fils `build`. Ou ils peuvent utiliser une image déjà existante, dans ce cas
ils auront un fils `image`.
Les autres fils sont les paramètres classiques que l'on va passer à `docker
run`.
### `volumes`
Cette section est le pendant de la commandes `docker volume`.
L'idée est d'éviter de créer des *Data Volume Container* qui ont une partie de
système de fichiers inutile, et de ne garder que l'idée d'emplacement servant
pour du stockage persistant.
On les déclare simplement en leur donnant un nom et un driver comme suit :
```yaml
volumes:
mysql-data:
driver: local
```
Leur utilisation est identique à un *Data Volume Container* : on référence le
nom ainsi que l'emplacement à partager :
```yaml
[...]
mysql:
[...]
volumes:
- mysql-data:/var/lib/mysql
```
### `network`
Cette section est le pendant de la commandes `docker network`.
Par défaut, Docker relie tous les conteneurs sur un bridge et fait du NAT pour
que les conteneur puisse accéder à l'Internet. Mais ce n'est pas le seul mode
possible !
De la même manière que pour les `volumes`, cette section déclare les réseaux
qui pourront être utilisés par les `services`. On pourrait donc avoir :
```yaml
networks:
knotdns-slave-net:
driver: bridge
```
#### Driver `host`
Le driver `host` réutilise la pile réseau de la machine hôte. Le conteneur
pourra donc directement accéder au réseau, sans NAT et sans redirection de
port. Les ports alloués par le conteneur ne devront pas entrer en conflits avec
les ports ouverts par la machine hôte.
#### Driver `null`
Avec le driver `null`, la pile réseau est recréée et aucune interface (autre
que l'interface de loopback) n'est présente. Le conteneur ne peut donc pas
accéder à Internet, ni aux autres conteneur, ...
Lorsque l'on exécute un conteneur qui n'a pas besoin d'accéder au réseau, c'est
le driver à utiliser. Par exemple pour un conteneur dont le but est de vérifier
un backup de base de données.
#### Driver `bridge`
Le driver `bridge` crée un nouveau bridge qui sera partagée entre tous les
conteneurs qui la référencent.
Avec cette configuration, les conteneurs ont accès à une résolution DNS des
noms de conteneurs qui partagent leur bridge. Ainsi, sans avoir à utiliser la
fonctionnalité de `link` au moment du `run`, il est possible de se retrouvé
lié, même après que l'on ait démarré. La résolution se fera dynamiquement.
### Utiliser le `docker-compose.yml`
Consultez <http://docs.docker.com/compose/compose-file/> pour une liste
exhaustive des options que vous pouvez utiliser.
Une fois que votre `docker-compose.yml` est 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 et admirer
le résultat :
```shell
docker-compose up
```
Encore une fois, testez la bonne connexion entre chronograf (accessible sur
<http://localhost:10000>) et influxdb.
## Rendu
Pour cette partie, vous devrez rendre la dernière itération de votre
`docker-compose.yml`.

View file

@ -1,18 +0,0 @@
\newpage
# Entrypoint
Jusque là, à chaque redémarrage d'InfluxDB, il est nécessaire de reconfigurer
Grafana pour lui indiquer la nouvelle IP du conteneur. En effet, le data
container préserve les données, mais un changement d'IP n'est pas
répercuté. Pour cela, il nous fait un script d'initialisation, qui va écrire
l'ip de notre conteneur Docker dans la table `data_source` :
Petit indice, les requêtes SQL sont les suivantes :
```
DELETE FROM "data_source";
INSERT INTO "data_source" VALUES(1,1,0,'influxdb','influx','direct','http://${}:8086/','user','pass','metrics',0,'','',0,'null','2015-10-29 09:00:00','2015-10-29 09:05:00');
```
La base se trouve dans `/var/lib/grafana/grafana.db`.

View file

@ -1,128 +0,0 @@
\newpage
Premières étapes
================
Dans un premier temps, nous allons créer une image Docker comme si l'on
réalisait une installation sur une machine classique : en suivant une recette,
sans trop se préoccuper des fonctionnalitées que propose Docker.
La machine (notre première image Docker) contiendra tout le nécessaire pour
faire fonctionner notre service de monitoring.
## Les caches
Nous avons vu que chaque instruction de notre `Dockerfile` génère une
couche. Chaque couche sert de cache d'une construction d'image à
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 base principalement sur le contenu de chaque instruction du
`Dockerfile` (pour les `COPY` et `ADD`, il va aussi regarder la date de
dernière modification de fichier à copier ou à ajouter). 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`.
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.
Pour profiter du cache, on va placer de préférences les étapes les plus
génériques (qui seraient les plus susceptibles d'apparaître dans d'autres
images), en haut du `Dockerfile`.
Commençons donc notre `Dockerfile` : choisissez une image de base pour remplir
votre `FROM`, et indiquez votre nom avec l'instruction `MAINTAINER` (pour
indiquez que c'est vous qui maintenez ce conteneur, si des utilisateurs ont besoin
de vous avertir pour le mettre à jour par exemple).
## `RUN` ou script ?
### InfluxDB
Ensuite vient la suite d'instructions pour installer d'InfluxDB. Le paquet
n'est pas disponible dans les dépôts. La
[procédure décrite du site](https://docs.influxdata.com/influxdb/v1.0/introduction/installation/#ubuntu-debian)
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.
* faire un `RUN` avec toutes ces opérations (sans oublier l'installation
préalable de `wget`/`curl`).
La copie étant définitive (supprimer le fichier ne le supprimera pas des
couches où il a pu exister), on préférera la seconde méthode, malgré que `wget`
restera en déchet. La première méthode aura plus sa place dans un dépôt de
projet où les binaires auront été préalablement compilés, il ne restera plus
qu'à les copier dans le conteneur au bon emplacement.
Écrivons 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 (`EXPOSE`, `CMD`, ...) et
[tester](http://localhost:8083) qu'InfluxDB est bien utilisable.
Il est possible que vous ayez à écraser le fichier de configuration via un
`COPY` (ou de manière plus maligne en utilisant `--volume` au moment du `docker
run`, cela ne fonctionne pas qu'avec les dossiers !). Ou peut-être ferez-vous
un `ENTRYPOINT` ?
### `telegraf`
`telegraf` est un programme qui permet de collecter des métriques systèmes. Il
travaille de paire avec InfluxDB, qu'il utilise pour stocker les valeurs
relevées.
Vous pouvez monitorer les métriques de n'importe quelle machine, simplement en
installant `telegraf` et en lui indiquant l'emplacement de son serveur
InfluxDB. Nous allons installer `telegraf` sur notre machine à l'aide de la
[documentation](https://docs.influxdata.com/telegraf/v1.0/introduction/installation/).
Ces quelques lignes devraient suffir à lancer la collecte, à condition que
votre InfluxDB écoute sur le port 8086 local :
```bash
TELEGRAF_VERSION=1.0.0
wget https://dl.influxdata.com/telegraf/releases/telegraf-${TELEGRAF_VERSION}_linux_amd64.tar.gz
tar xf telegraf-${TELEGRAF_VERSION}_linux_amd64.tar.gz
TELEGRAF_CONFIG_PATH=./telegraf/etc/telegraf/telegraf.conf ./telegraf/usr/bin/telegraf
```
Rendez-vous ensuite dans [l'interface d'InfluxDB](http://localhost:8083/) pour
voir si la collecte se passe bien.
Dans l'interface sélectionnez la base `telegraf` puis explorez les valeurs :
```sql
SHOW MEASUREMENTS
SHOW FIELD KEYS
SELECT usage_idle FROM cpu WHERE cpu = 'cpu-total' ORDER BY time DESC LIMIT 5
```
Laissons tourner `telegraf` afin de constituer un petit historique de valeurs.
## Rendu
### Questions
1. Dans quel langage est écrit `telegraf` ?
1. Quelle(s) particularité(s) de ce langage permet de se passer de la variable
`LD_LIBRARY_PATH` au lancement de `telegraf`, alors qu'on ne l'a pas
installé ?
### Éléments à rendre
Avant de passer à la suite, placez votre `Dockerfile` et les éventuels fichiers
annexes dans un dossier `influxdb`.

View file

@ -1,226 +0,0 @@
\newpage
Retour sur les bonnes pratiques
===============================
Pour chaque bonne pratique ci-dessous, vérifiez que vous la respectez
bien, faites les modifications nécessaires.
## Utilisez le fichier `.dockerignore`
Dans la plupart des cas, vos `Dockerfile` seront dans des dossiers contenant
beaucoup de fichiers qui ne sont pas nécessaire à la construction de votre
conteneur (par exemple, vous pouvez avoir un `Dockerfile` placé à la racine
d'un dépôt git : il va avoir besoin des binaires compilés, mais pas des
sources).
Afin d'améliorer les performances lors de la construction, vous pouvez exclure
les fichiers et dossiers inutiles au conteneur en ajoutant un fichier
`.dockerignore` dans le répertoire de votre `Dockerfile`.
Ce fichier fonctionne de la même manière que le `.gitignore` : vous pouvez
utiliser du globing.
Pour plus d'informations, vous pouvez consulter la documentation accessible à
<http://docs.docker.com/reference/builder/#dockerignore-file>.
## N'installez rien de superflu
Afin de réduire la quantité de dépendances à installer, n'installez pas de
paquets dont vous n'avez pas vraiment l'utilité : il n'y a pas de raison par
exemple d'avoir un éditeur de texte dans un environnement qui sera utilisé
comme serveur web. Un autre conteneur pourra contenir cet éditeur de texte dans
les cas où vous avez besoin de modifier des données.
En plus, cela réduira le temps de build et la taille des images produites !
## Minimisez le nombre de couches
Vous devez trouver l'équilibre idéal entre la lisibilité de votre `Dockerfile`
(qui assure la maintenabilité sur le long-terme) et le nombre de couches
créées.
## Ordonnez vos lignes de commandes complexes
### Allez à la ligne pour séparer les longues lignes de commandes complexes
Aérez vos `Dockerfile` !
N'hésitez pas à commenter et séparer les blocs logiques ensemble, comme lorsque
vous codez.
Lorsqu'une ligne devient complexe, allez à la ligne :
```
RUN apt-get update && apt-get install -y \
nginx \
php5-fpm
```
Notez les backslashs à la fin des lignes, indiquant qu'elle n'est pas terminée.
### Triez les arguments par ordre alphabétique
Lorsque c'est possible, ordonnez vos lignes suivant un ordre logique. Par
exemple :
```
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
```
## Profitez du système de cache
Le processus de construction de votre image Docker va lire les informations de
votre Dockerfile dans l'ordre. Pour chaque instruction, Docker va essayer de
trouver si une image n'est pas déjà disponible dans le cache (plutôt que de
créer une nouvelle image identique).
Il y a un certain nombre de règles à connaître pour bien utiliser ce mécanisme :
- En démarrant d'une image de base déjà présente dans le cache (`docker
images`), l'instruction suivante est comparée avec toutes les autres images
existantes qui en dérivent directement. Si aucune image correspondant n'est
trouvé pour l'instruction, le cache est invalidé pour le reste de cette
construction.
- Dans la plupart des cas, Docker va simplement comparer l'instruction lue avec
le(s) différente(s) image(s) qui dérive(nt) de la commande précédente. Si
aucune commande correspondante n'est trouvé, le cache se retrouve invalidé
pour les instructions suivantes.
- Pour les instructions `ADD` et `COPY`, en plus de la comparaison précédente,
la somme de contrôle du fichier est ajoutée. Si le fichier a été modifié, le
cache se retrouve invalidé.
- Une fois que le cache est invalidé, toutes les commandes restantes à exécuter
dans le `Dockerfile` vont être exécutées.
## Concevez des conteneur éphémères
Les conteneurs que vous générez doivent être aussi éphémères que possible : ils
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.
## Cas d'`apt-get` et des gestionnaires de paquets
- N'exécutez pas `apt-get update` seul sur une ligne. Cela risque de poser des
problèmes de cache, car la ligne ne va jamais changer et le cache sera
toujours utilisé. Vous risquez de récupérer des paquets qui ne sont pas à
jour.
- Évitez de mettre à jour le système fourni (via `apt-get upgrade` ou `apt-get
update`). Si l'image n'est pas à jour, contactez son mainteneur. Si vous avez
besoin d'une version à jour d'un paquet distribué avec l'image, préférez
l'utilisation d'`apt-get install -y foo` qui mettra à jour exclusivement le
paquet `foo`, sans altérer le reste du système.
- Pour assurer une bonne gestion du cache, n'hésitez pas à indiquer les
versions des programmes que vous voulez installer sur votre ligne de commande
`apt-get`.
## Exposez les ports standards
La commande `EXPOSE` vous permet d'indiquer les ports sur lesquels votre
conteneur s'attend à recevoir des paquets venant de l'extérieur. Ces ports ne
sont pas partagés avec l'hôte ou les autres conteneur, donc vous n'avez pas de
raison de ne pas utiliser les ports standards.
Si vous faites cela, il y a de forte chance qu'il n'y ait pas besoin de
modifier la configuration des autres logiciels contenu dans d'autres conteneurs
puis qu'ils sont généralement configurés pour se connecter aux ports standards.
S'il y a un conflit sur la machine hôte, il sera toujours temps de créer une
redirection à ce moment là.
## La bonne utilisation de l'`ENTRYPOINT`
L'entrypoint peut être utilisé de deux manières différentes :
- Vous pouvez l'utiliser de telle sorte que la commande passée au `docker run`,
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;"]
```
- 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 :
```shell
#!/bin/bash
set -e
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
fi
exec gosu postgres "$@"
fi
exec "$@"
```
## `[""]`, `'` et sans `[]`
Les instructions `ENTRYPOINT` et `CMD` peuvent prendre deux formes :
- `["cmd", "arg1", "arg2"]` : ici, un simple `exexve` sera effectué avec ces
arguments. Si d'éventuels variables se trouve dans les arguments, elles ne
seront pas remplacées.
- `cmd arg1 arg2` : ici l'exécution se fera au sein d'un `sh -c`, donc les
variables seront remplacés et étendues.
Les commandes sous forme de tableau étant parsées par un parser JSON, vous ne
pouvez pas utiliser les simple quotes.
## Volumes
L'instruction `VOLUME` doit être utilisée pour exposer tous les espaces de
stockage de données, configuration, ...
## Réduisez les privilèges
Utilisez l'instruction `USER` dès que vous le pouvez, lorsqu'un service ne
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
processus par conteneur. Il est préférable de répartir chaque application dans
un conteneur distinct qui n'effectue que le travail pour lequel il est
chargé. Les options de liaison entre conteneur sont à votre disposition pour
vous aider à cette tâche.

View file

@ -1,50 +0,0 @@
\newpage
Installation
============
## `docker-compose`
Pour ce TP, nous allons avoir besoin de `docker-compose`.
Ce projet ne bénéficie pas d'une intégration au sein du projet Docker et doit
être téléchargé séparément, car originellement, le projet était développé par
une équipe indépendante. S'étant révélé primordiale, ils ont trouvé une place
au sein du projet Docker, mais l'incompatibilité des langages utilisés fait que
`docker-compose` n'est toujours pas intégré dans docker.
### Par le gestionnaire de paquets
Les distributions à jour vous proposeront un paquet `docker-compose` qui
fonctionnera avec la version de Docker qu'ils fournissent.
### Par la distribution binaire
L'équipe en charge de Docker compose met à disposition un exécutable contenant
tous les scripts. Nous pouvons l'installer en suivant la procédure suivante :
```shell
curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-Linux-x86_64 \
> /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose
```
### `pip`
Le projet étant écrit en Python, il est également disponible via `pip`, si vous
préférez cette méthode. N'oubliez pas de préciser une version compatible avec
votre version de Docker.
### Vérification du fonctionnement
Comme avec Docker, nous pouvons vérifier le bon fonctionnement de
`docker-compose` en exécutant la commande :
```
42sh$ docker-compose --version
docker-compose version: 1.8.0
```
Si vous obtenez une réponse similaire, c'est que vous êtes prêt à commencer le
TP ! Alors n'attendons pas, partons à l'aventure !

View file

@ -1,50 +0,0 @@
\newpage
Rendu
=====
## Projet
Amusez-vous à la piscine, il n'y a pas de projet en plus des exercices fait en
TP !
En complément de ce TP, vous pouvez jetez un œil à
[Docker Swarm](https://docs.docker.com/engine/swarm) !
## Modalité de rendu
Un service automatique s'occupe de réceptionner vos rendus, de faire les
vérifications nécessaires et de vous envoyer un accusé de réception (ou de
rejet).
Ce service écoute sur l'adresse <virli@nemunai.re>, c'est donc à cette adresse
et exclusivement à celle-ci que vous devez envoyer vos rendus. Tout rendu
envoyé à une autre adresse et/ou non signé ne sera pas pris en compte.
## Tarball
Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...).
Les réponses aux questions sont à regrouper dans un fichier `questions.txt` à
placer à la racine de votre rendu.
Voici une arborescence type:
```
login_x-TP2/questions.txt
login_x-TP2/docker-compose.yml
login_x-TP2/influxdb
login_x-TP2/influxdb/Dockerfile
login_x-TP2/influxdb/influxdb.conf
login_x-TP2/chronograf
login_x-TP2/chronograf/Dockerfile
login_x-TP2/chronograf/chronograf.conf
login_x-TP2/mymonitoring
login_x-TP2/mymonitoring/Dockerfile
login_x-TP2/mymonitoring/chronograf.conf
login_x-TP2/mymonitoring/influxdb.conf
login_x-TP2/mymonitoring/supervisor.conf
```

View file

@ -1,100 +0,0 @@
\newpage
Plusieurs daemons dans un conteneur
===================================
Notre système de monitoring commence enfin à ressembler à quelque chose. Mais
ce serait tellement plus pratique de voir tous ces tableaux de nombres sous
forme de graphiques !
Nous allons pour cela ajouter `chronograf` dans notre image.
Avant de modifier votre `Dockerfile`, créez un nouveau dossier de rendu :
`mymonitoring`, dans lequel vous recopierez l'état actuel de notre image
`influxdb`.
## Chronograf
Commençons par compléter la commande d'installation existante pour `influxdb`,
afin d'installer simultanément `chronograf`.
La documentation de la procédure est disponible
[à cette adresse](https://docs.influxdata.com/chronograf/v1.0/introduction/installation/).
## Script d'init
Lors du dernier TP, nous avons vu que les conteneurs s'arrêtaient dès que le
premier processus du conteneur (celui qui a le PID 1, à la place d'`init`)
terminait son exécution, quelque soit le statut de ses éventuels fils.
Pour lancer tous nos daemons, nous avons donc besoin d'écrire un script qui
lance puis attend que les deux deamons aient terminés de s'exécuter.
Écrivons ce script. Hints : `wait(1)`.
\vspace{1em}
Pour vérifier que votre conteneur fonctionne correctement, vous pouvez le
lancer :
```shell
docker run --rm -p 10000:10000 mymonitoring
```
Puis accéder à chronograf : <http://localhost:10000/>. Donnez un nom à votre
configuration, puis cliquez sur *Add*. Les paramètres préremplis dans le
formulaire sont corrects.
Vous devriez obtenir l'écran suivant (notez la partie `Status: Online, v1.0.0`) :
![Chronograf configuré](chronograf_setup.png)
## 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` :
```shell
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.
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.
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 `chronograf` et `influxdb`.
Vous pouvez vous aider de la documentation disponible à :
<http://supervisord.org/configuration.html>
La même procédure de test que précédemment peut être suivie.
## Rendu
Nous ne toucherons plus à cette image, placez-la dans un dossier
`mymonitoring`.

View file

@ -1,25 +0,0 @@
---
title: Virtualisation légère -- TP n^o^ 2
subtitle: Aller plus loin avec Docker
author: Pierre-Olivier *Nemunaire* Mercier
institute: EPITA
date: Jeudi 15 septembre 2016
...
Durant ce deuxième TP, nous allons approfondir l'utilisation de Docker !
Tous les éléments de ce TP (exercices et questions) sont à rendre à
<virli@nemunai.re> au plus tard le jeudi 6 octobre 2016 à 8 h 42. Consultez la
dernière section de chaque partie pour plus d'information sur les éléments à
rendre.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
[faire signer votre clef](http://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
Vous pouvez utiliser l'adresse <signcheck@nemunai.re> pour savoir si vous vous
y prenez correctement.
\hypersetup{linkcolor=black}
\tableofcontents

View file

@ -1,18 +0,0 @@
\newpage
But du TP
=========
Aujourd'hui, nous allons réaliser un système de monitoring.
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.
Nous collecterons les données d'utilisation de votre machine avec
[Telegraf](https://www.influxdata.com/time-series-platform/telegraf/). Ces
données seront envoyés vers
[InfluxDB](https://www.influxdata.com/time-series-platform/influxdb/), puis
elles seront affichées sous forme de graphique grâce à
[Chronograf](https://www.influxdata.com/time-series-platform/chronograf/).
![Dashboard de l'utilisation CPU et mémoire sur Chronograf](chronograf.png)