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

@ -0,0 +1,22 @@
SOURCES = tutorial.md interactive.md dockerfile.md first.md supervisor.md goodpractices.md split.md entrypoint.md multistaged.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.

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -0,0 +1,142 @@
\newpage
`Dockerfile`
============
## Ma première image ... par `Dockerfile`
Pour construire une image, nous ne sommes pas obligés de passer par une série
de commits. Docker dispose d'un mécanisme permettant d'automatiser la
construction de nouvelles images. Vous pouvez arriver au même résultat que ce
que l'on a réussi à faire précédemment en utilisant le `Dockerfile` suivant :
```
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y nano
```
La syntaxe d'un `Dockerfile` est simple, le premier mot de chaque ligne est
l'intitulé d'une instruction (que l'on écrit généralement en majuscule), elle
est suivie de ses arguments.
Dans notre exemple, nous utilisons `FROM` qui indique une image de départ à
utiliser ; `RUN` est une commande qui sera exécutée dans le conteneur, dans le
but de le construire.
Pour lancer la construction de la nouvelle image, créer un nouveau dossier ne
contenant que votre fichier `Dockerfile`, placez-vous dedans, puis utilisez la
commande `build` :
```
docker image build --tag=my_editor .
```
Une fois la construction de l'image terminée, vous pouvez la lancer et
constater l'existence de notre éditeur favori :
```
docker container run -it my_editor /bin/bash
```
## `RUN` dans le `Dockerfile`
Dans un `Dockerfile`, chaque ligne est exécutée indépendamment des
autres et correspondra à une nouvelle couche de notre image.
Cela signifie que l'exemple suivant **ne fonctionne pas** :
```
COPY db.sql /db.sql
RUN service mysqld start
RUN mysql -u root -p toor virli < /db.sql
```
Cet exemple ne fonctionne pas car le serveur MySQL est lancé dans le premier
RUN, n'est plus lancé au moment du deuxième RUN. En effet, chaque commande du
`Dockerfile` a pour but de modifier le système de fichiers.
Pour avoir le résultat escompté, il faut exécuter les commandes ensemble :
```
COPY db.sql /db.sql
RUN service mysqld start && mysql -u root -p toor virli < /db.sql
```
Après le `RUN`, MySQL sera de nouveau arrêté, si on veut l'utiliser dans le
conteneur, il ne faudra pas oublier de lancer le processus.
## Exposer des ports
Construisons maintenant un conteneur avec un serveur web :
```
FROM my_editor
RUN apt-get update
RUN apt-get install -y nginx
EXPOSE 80
```
L'instruction `EXPOSE` sera traité plus tard par le client Docker
(équivalent à l'argument `--expose`). Il s'agit de préciser les ports
sur lesquels votre image écoute.
En utilisant l'option `-P` du `run`, vous allez pouvoir assigner une
redirection de port aléatoire sur la machine hôte vers votre
conteneur :
```
docker image build --tag=my_webserver .
docker container run -it -P my_webserver /bin/bash
service nginx start
```
Dans un autre terminal, lancer un `docker ps` et consulter la colonne
*PORTS* pour connaître le port choisit par Docker pour effectuer la
redirection.
Rendez-vous ensuite dans votre navigateur sur <http://localhost:49153/>.
À vous de jouer : utilisez l'instruction `COPY` pour afficher votre
propre `index.html` remplaçant celui installé de base par nginx.
## Lancement de commande automatique
Vous pouvez placer dans un `Dockerfile` une instruction `CMD` qui sera
exécutée si aucune commande n'est passée lors du `run`, par exemple :
```
CMD nginx -g "daemon off;"
```
```
docker image build --tag=my_nginx .
docker container run -d -P my_nginx
```
L'option `-d` passée au `run` lance le conteneur en tâche de
fond. Si vous constatez via un `docker ps` que le conteneur s'arrête
directement, retirer cette option pour voir ce qui ne va pas, ou
utilisez la commande `docker logs`.
## D'autres instructions ?
Consultez <https://docs.docker.com/engine/reference/builder/> pour la liste complète
des instructions reconnues.
## Rendu
Rendez le fichier `Dockerfile` et son contexte (`index.html`, fichiers de conf
éventuels, ...) que vous avez utilisé pour réaliser votre image
`my_webserver`.
Une attention particulière sera apporté au respect des différentes bonnes
pratiques vues en cours pour l'écriture de `Dockerfile`.

View file

@ -0,0 +1,19 @@
\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

@ -0,0 +1,137 @@
\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és 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` est exécutée dans un
conteneur, qui génère ensuite une image intermédiaire. Cette image
intermédiaire sert ensuite d'image de base pour l'instruction suivante.
Lorsque l'on lance la reconstruction du même `Dockerfile`, les images
intermédiaires sont utilisées comme un cache d'instructions, permettant ainsi
de gagner du temps sur les étapes qui n'ont pas changées. 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 image
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 `LABEL maintainer` (pour
indiquer que c'est vous qui maintenez cette image, si des utilisateurs ont
besoin de vous avertir pour le mettre à jour ou s'ils rencontrent des
difficultés 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[^debrepos]. La
[procédure décrite du site](https://portal.influxdata.com/downloads) incite à
télécharger le paquet mis à disposition puis à l'installer via `dpkg -i`.
[^debrepos]: Le projet met à disposition des dépôts, si vous préférez cette
méthode, consultez la
[documentation d'installation](https://docs.influxdata.com/influxdb/v1.3/introduction/installation/#ubuntu-debian).
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

@ -0,0 +1,226 @@
\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

@ -0,0 +1,59 @@
\newpage
Modification interactive
========================
Nous voilà maintenant dans le conteneur ! Il est assez épuré, il n'y a rien de
superflu : même pas d'éditeur de texte : ni vim, ni emacs, même pas `vi` !
La première chose à faire est de télécharger la liste des paquets. En effet,
afin de ne pas livrer de superflu, la liste des paquets et son cache ne sont
pas inclues dans le conteneur.
```
apt-get update
```
Il peut arriver que des paquets présents dans l'image ne soient pas à
jour. Afin de garder un environnement cohérent, il est recommandé de ne pas
utiliser le gestionnaire de paquets pour mettre à jour les paquets présent de
base, mais plutôt de contacter le mainteneur de l'image pour qu'il la mette à
jour.
Installons maintenant un programme :
```
apt-get install nano
```
En attendant la fin de l'installation, jetons un œil à la commande dans un
autre terminal :
```
docker container ls
```
Cette commande liste les conteneurs actifs. Notez le *Container ID* ainsi que
le *NAMES* du conteneur du conteneur actuellement en cours d'installation de
`nano`.
Lorsque l'installation de `nano` est terminée, quittez l'image en tapant
`exit`.
Sauvegardez votre image modifiée avec la commande `commit` pour pouvoir
commencer directement de votre image avec `nano` :
```
docker container commit CONTAINER my_nano
```
En remplaçant `CONTAINER` par le nom ou l'identifiant de votre
container. `my_nano` est le nom que vous voudrez utiliser à la place
d'`ubuntu` :
```
docker container run -it my_nano /bin/bash
```
Vous constatez cette fois que vous pouvez lancer `nano`, alors que vous ne
pouvez toujours pas le faire dans un conteneur issue d'une image `ubuntu` !

View file

@ -0,0 +1,6 @@
\newpage
Multi-stage build
=================
TODO

View file

@ -0,0 +1,54 @@
\newpage
Une application par conteneur
=============================
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
```

View file

@ -0,0 +1,103 @@
\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 !
## `HEALTHCHECK`
## `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

@ -0,0 +1,23 @@
---
title: Virtualisation légère -- TP n^o^ 3
subtitle: Construire des images Docker
author: Pierre-Olivier *Nemunaire* Mercier
institute: EPITA
date: Jeudi 11 octobre 2018
...
Durant ce troisième TP, nous allons voir comment créer nos propres images !
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le jeudi 18 octobre 2018 à 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/).
\hypersetup{linkcolor=black}
\tableofcontents