diff --git a/tutorial/docker-advanced/chronograf_setup.png b/tutorial/docker-advanced/chronograf_setup.png
deleted file mode 120000
index dcbd7d3..0000000
--- a/tutorial/docker-advanced/chronograf_setup.png
+++ /dev/null
@@ -1 +0,0 @@
-../dockerfiles/chronograf_setup.png
\ No newline at end of file
diff --git a/tutorial/docker-advanced/chronograf_setup.png b/tutorial/docker-advanced/chronograf_setup.png
new file mode 100644
index 0000000..25d005a
Binary files /dev/null and b/tutorial/docker-advanced/chronograf_setup.png differ
diff --git a/tutorial/dockerfiles/Makefile b/tutorial/dockerfiles/Makefile
index bce6f31..df48fcd 100644
--- a/tutorial/dockerfiles/Makefile
+++ b/tutorial/dockerfiles/Makefile
@@ -1,4 +1,4 @@
-SOURCES = tutorial.md interactive.md dockerfile.md first.md supervisor.md goodpractices.md split.md entrypoint.md multistaged.md rendu.md
+SOURCES = tutorial.md interactive.md dockerfile.md goodpractices.md entrypoint.md rendu.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
diff --git a/tutorial/dockerfiles/chronograf_setup.png b/tutorial/dockerfiles/chronograf_setup.png
deleted file mode 100644
index 25d005a..0000000
Binary files a/tutorial/dockerfiles/chronograf_setup.png and /dev/null differ
diff --git a/tutorial/dockerfiles/dockerfile.md b/tutorial/dockerfiles/dockerfile.md
index b4471b2..60f9922 100644
--- a/tutorial/dockerfiles/dockerfile.md
+++ b/tutorial/dockerfiles/dockerfile.md
@@ -1,13 +1,11 @@
\newpage
-`Dockerfile`
-============
-
-## Ma première image ... par `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
+de *commits*. Docker dispose d'un mécanisme permettant d'automatiser la
+construction de nouvelles images. Nous pouvons arriver au même résultat que ce
que l'on a réussi à faire précédemment en utilisant le `Dockerfile` suivant :
@@ -19,7 +17,7 @@ que l'on a réussi à faire précédemment en utilisant le `Dockerfile` suivant
```
-La syntaxe d'un `Dockerfile` est simple, le premier mot de chaque ligne est
+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.
@@ -27,9 +25,9 @@ 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` :
+Pour lancer la construction de la nouvelle image, créons un nouveau dossier ne
+contenant que votre fichier `Dockerfile`, plaçons-nous ensuite dedans, puis
+lançons la commande `build` :
```
@@ -37,7 +35,7 @@ commande `build` :
```
-Une fois la construction de l'image terminée, vous pouvez la lancer et
+Une fois la construction de l'image terminée, nous pouvons la lancer et
constater l'existence de notre éditeur favori :
@@ -62,9 +60,21 @@ Cela signifie que l'exemple suivant **ne fonctionne pas** :
```
-Cet exemple ne fonctionne pas car le serveur MySQL qui 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.
+Cet exemple ne fonctionne pas car le serveur MySQL est bien lancé dans le
+premier `RUN`, mais il se trouve brûtalement arrêté dès lors que la commande
+`service` se termine. En fait, à chaque instruction, Docker réalise
+automatiquement un `run` suivi d'un `commit`. Et vous pouvez constater par
+vous-même que, en créant l'image `tinysql` à partir d'un simple `apt install
+mysql` :
+
+
+```
+ docker container run tinysql service mysqld start
+```
+
+
+rend la main directement, sans laisser de `mysqld` dans l'arborescence de
+processus.
Pour avoir le résultat escompté, il faut exécuter les commandes ensemble :
@@ -75,13 +85,17 @@ Pour avoir le résultat escompté, il faut exécuter les commandes ensemble :
```
-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.
+Après le `RUN`, MySQL sera de nouveau tué.
+
+En aucun cas, une commande exécutée par un `RUN` se retrouvera en cours
+d'exécution lorsque l'on invoquera un conteneur par `docker container
+run`. Seul la commande fournie par l'utilisateur ou la commande par défaut de
+l'image sera exécutée au lancement d'un conteneur.
## Exposer des ports
-Construisons maintenant un conteneur avec un serveur web :
+Construisons maintenant un conteneur avec un service web :
```
@@ -95,30 +109,90 @@ Construisons maintenant un conteneur avec un serveur web :
L'instruction `EXPOSE` sera traitée plus tard par le client Docker (équivalent
-à l'argument `--expose`). Il s'agit de préciser les ports sur lesquels votre
-image écoute.
+à l'argument `--expose`). Il s'agit d'une métadonnée qui sera attachée à
+l'image (et à toutes ses images filles).
-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 :
+En précisant tous les ports qu'exposent une image dans ses métadonnées, ces
+ports seront automatiquement exposés en utilisant l'option `-P` du `run` : cela
+assigne 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
+ 42sh$ docker image build --tag=my_webserver .
+ 42sh$ docker container run -it -P my_webserver /bin/bash
+ (cntnr)# service nginx start
```
-Dans un autre terminal, lancer un `docker ps` et consulter la colonne *PORTS*
-pour connaître le port choisi par Docker pour effectuer la redirection.
+Dans un autre terminal, lancer un `docker container ls` et consulter la colonne
+*PORTS* pour connaître le port choisi par Docker pour effectuer la redirection.
Rendez-vous ensuite dans votre navigateur sur .
*À vous de jouer :* utilisez l'instruction `COPY` pour afficher votre propre
-`index.html` remplaçant celui installé de base par nginx.
+`index.html` remplaçant celui installé de base par `nginx`. Si vous manquez
+d'inspiration, utilisez [cette page de compte à
+rebours](https://virli.nemunai.re/countdown.html).
-## Lancement de commande automatique
+## Les caches
+
+Nous avons vu que chaque instruction de notre `Dockerfile` est exécutée dans un
+conteneur, qui génère une image intermédiaire. Cette image intermédiaire sert
+ensuite d'image de base pour le conteneur qui sera lancé avec l'instruction
+suivante.
+
+Lorsqu'on lance la reconstruction du même `Dockerfile`, les images
+intermédiaires sont réutilisées, comme un cache d'instructions. Cela permet 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 (rappelez-vous le principe d'union FS).
+
+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`.
+
+
+## Métadonnées pures
+
+L'instruction LABEL permet d'ajouter une métadonnée à une image, sous forme de
+clef/valeur.
+
+Une métadonnée
+[courante](https://github.com/nginxinc/docker-nginx/blob/master/mainline/stretch/Dockerfile#L3)
+est d'indiquer le nom du mainteneur de l'image :
+
+
+```
+ LABEL maintainer="Pierre-Olivier Mercier "
+```
+
+
+Dans notre `Dockerfile`, indiquez juste après l'image de base, vos noms,
+prénoms et mails de contact 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.
+
+On le place dès le début, car comme c'est une information qui n'est pas amener
+à changer, elle sera toujours retrouvée en cache.
+
+
+## Commande par défaut
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 :
@@ -131,8 +205,8 @@ si aucune commande n'est passée lors du `run`, par exemple :
```
- docker image build --tag=my_nginx .
- docker container run -d -P my_nginx
+ 42sh$ docker image build --tag=my_nginx .
+ 42sh$ docker container run -d -P my_nginx
```
@@ -142,16 +216,104 @@ retirez cette option pour voir ce qui ne va pas, ou utilisez la commande
`docker container logs`.
+## Construire son application au moment de la construction du conteneur ?
+
+Comment faire lorsque l'on a besoin de compiler une application avant de
+l'intégrer dans le conteneur ?
+
+On peut vouloir lancer la compilation sur notre machine, mais cela ne sera pas
+très reproductible et cela aura nécessité d'installer le compilateur et les
+outils liés au langage que l'on souhaite compiler. Peut-être que plusieurs
+versions de ces outils existent, laquelle choisir ? ... Ok c'est trop
+compliqué.
+
+D'un autre côté, si l'on fait cela dans un conteneur, celui-ci contiendra dans
+ses couches des données inutiles à l'exécution : les sources, les produits
+intermédiaires de compilation, le compilateur, n'ont rien à faire dans les
+couches de notre image.
+
+Le meilleur des deux mondes se trouve dans les *Multi-stage builds* : au sein
+du même `Dockerfile`, on va réaliser les opérations de préparation dans un ou
+plusieurs conteneurs, avant d'agréger le contenu compilé au sein du conteneur
+final :
+
+
+```
+ FROM gcc:4.9
+ COPY . /usr/src/myapp
+ WORKDIR /usr/src/myapp
+ RUN gcc -static -static-libgcc -o hello hello.c
+
+ FROM scratch
+ COPY --from=0 /usr/src/myapp/hello /hello
+ CMD ["/hello"]
+```
+
+
+Dans cet exemple, deux conteneurs distincts sont créés : le premier à partir de
+l'image `gcc`, il contient tout le nécessaire pour compiler notre
+`hello.c`. Mais l'image finale (le dernier `FROM` de notre `Dockerfile`) est
+l'image vide, dans laquelle nous recopions simplement le produit de notre
+compilation.
+
+L'image ainsi générée est minime, car elle ne contient rien d'autre que le
+strict nécessaire pour s'exécuter.
+
+### Étapes nommées
+
+Nous avons utilisé `--from=0` pour désigner la première image de notre
+`Dockerfile`. Lorsque l'on réalise des montages plus complexe, on peut vouloir
+donner des noms à chaque image, plutôt que de devoir jongler avec les
+numéros. Dans ce cas, on indiquera :
+
+
+```
+ FROM gcc:4.9 as builder
+ COPY . /usr/src/myapp
+ WORKDIR /usr/src/myapp
+ RUN gcc -static -static-libgcc -o hello hello.c
+
+ FROM scratch
+ COPY --from=builder /usr/src/myapp/hello /hello
+ CMD ["/hello"]
+```
+
+
+Par défaut la dernière étape du `Dockerfile` est retenu comme étant l'image que
+l'on souhaite `tagger`, mais il est possible de préciser quelle image
+spécifiquement on souhaite construire avec l'option `--target` :
+
+
+```
+ 42sh$ docker build --target builder -t hello-builder .
+```
+
+
+Cela peut être particulièrement utile si l'on dispose d'une image de debug,
+incluant tous les symboles, et une image de production, plus propre. On
+sélectionnera ainsi avec l'option `--target` l'un ou l'autre en fonction de
+l'environnement dans lequel on souhaite se déployer.
+
+
## D'autres instructions ?
Consultez pour la liste
complète des instructions reconnues.
-## Rendu
+## Exercice
-Rendez le fichier `Dockerfile` et son contexte (`index.html`, fichiers de conf
-éventuels, ...) que vous avez utilisé pour réaliser votre image `my_webserver`.
+Pour mettre en application tout ce que nous venons de voir, réalisons le
+`Dockerfile` du service web [`youp0m`](https://you.p0m.fr/) que nous avons
+utilisé la semaine dernière.
-Une attention particulière sera apportée au respect des différentes bonnes
-pratiques vues en cours pour l'écriture du `Dockerfile`.
+Pour réaliser ce genre de contribution, on ajoute généralement un `Dockerfile`
+à la racine du dépôt.
+
+Vous pouvez cloner le dépôts de sources de `youp0m` à :
+
+
+```
+ https://git.nemunai.re/youp0m.git
+```
+
diff --git a/tutorial/dockerfiles/entrypoint.md b/tutorial/dockerfiles/entrypoint.md
index c1e560c..28288dc 100644
--- a/tutorial/dockerfiles/entrypoint.md
+++ b/tutorial/dockerfiles/entrypoint.md
@@ -1,21 +1,114 @@
\newpage
-Entrypoint
-==========
+Personnalisation du point d'entrée du conteneur
+===============================================
-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` :
+## Point d'entrée basique
-Petit indice, les requêtes SQL sont les suivantes :
+Afin de faire bénéficier à nos utilisateurs d'une immersion parfaite, nous
+allons faire en sorte que notre image permette d'être utilisée ainsi :
```
- 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');
+ 42sh$ docker run -d -p 80:80 youp0m -bind 80
```
-La base se trouve dans `/var/lib/grafana/grafana.db`.
+
+Plutôt que de laisser l'utilisateur se débrouiller avec le chemin interne dans
+lequel il va trouver le bon binaire :
+
+
+```
+ 42sh$ docker run -d -p 80:80 youp0m /srv/youp0m -bind 80
+```
+
+
+Essayez les deux commandes, si vous avez utilisé l'instruction `CMD` dans votre
+`Dockerfile` jusqu'à présent, vous devez vous trouver dans le deuxième cas.
+
+Pour améliorer la situation, définissez
+l'[`ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint)
+de votre image sur le binaire `/srv/youp0m`.
+
+
+## Point d'entrée avancé
+
+Dans certains cas, il peut être nécessaire au lancement d'un conteneur, de
+faire un minimum d'étapes d'initialisation avant que le conteneur ne soit
+opérationnel (rappelez-vous les options que l'on passait à l'image `mysql` pour
+créer un utilisateur et une base).
+
+Notre but, dans cette partie, sera de créer un utilisateur administrateur
+(pouvant passer le contrôle d'accès ) :
+
+
+```
+ 42sh$ docker run -i --rm -p 8080:8080 -e YOUP0M_PASSWORD=admin youp0m
+```
+
+
+### Bases du script
+
+Notre script d'`ENTRYPOINT` sera appelé avec en argument, ceux passés par
+l'utilisateur après le nom de l'image, ou, à défaut, le contenu de `CMD`.
+
+C'est donc l'`ENTRYPOINT` qui est responsable de la bonne utilisation de
+ceux-ci, de leur modification, ...
+
+À la fin d'un script d'`ENTRYPOINT`, afin de garder comme premier processus du
+conteneur le programme qui nous intéresse, on réalise un `execve(2)`, sans
+`fork(2)` :
+
+
+```shell
+ exec /srv/youp0m $@
+```
+
+
+Dans cet exemple : `exec` est la commande interne à notre shell pour lui
+indiquer de remplacer son fil d'exécution par cette commande (sans `exec`, il
+va `fork(2)` avant). `$@` est ici pour transmettre tel quel la liste des
+arguments passés au script (il s'agit de ceux donnés par l'utilisateur, sur la
+ligne de commande du `run`, ou du contenu de `CMD` si l'utilisateur n'a rien
+précisé).
+
+
+### Format du fichier `htpasswd`
+
+Le format attendu est celui d'un fichier `htpasswd` typique d'Apache. Vous
+pourriez obtenir un fichier valide avec :
+
+
+```shell
+ (
+ echo -n "$YOUP0M_USERNAME"
+ echo -n ":"
+ openssl passwd -crypt "$YOUP0M_PASSWORD"
+ ) > myhtpasswd
+```
+
+
+Il faut ensuite passer le fichier sur la ligne de commande grâce à l'option
+`-htpasswd`.
+
+
+### Exercice
+
+Écrivez un script d'`ENTRYPOINT`, analysant les variables d'environnement, à la
+recherche de `YOUP0M_USERNAME` et `YOUP0M_PASSWORD` pour initialiser le fichier
+`.htpasswd` qui sera ajouté à la liste des arguments à passer au service.
+
+Par exemple :
+
+
+```
+ 42sh$ docker run -d -p 8081:8081 -e YOUP0M_USERNAME=admin -e YOUP0M_PASSWORD=admin youp0m -bind=8081
+
+ 42sh$ curl -u admin:badpasswd http://localhost:8081/admin/
+ You are not allowed to perform this request.
+
+ 42sh$ curl -u admin:admin http://localhost:8081/admin/
+
+```
+
diff --git a/tutorial/dockerfiles/first.md b/tutorial/dockerfiles/first.md
index cbe3a62..cc389ed 100644
--- a/tutorial/dockerfiles/first.md
+++ b/tutorial/dockerfiles/first.md
@@ -11,40 +11,6 @@ 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 ?
diff --git a/tutorial/dockerfiles/goodpractices.md b/tutorial/dockerfiles/goodpractices.md
index 482a39c..33cb584 100644
--- a/tutorial/dockerfiles/goodpractices.md
+++ b/tutorial/dockerfiles/goodpractices.md
@@ -4,7 +4,7 @@ Retour sur les bonnes pratiques
===============================
Pour chaque bonne pratique ci-dessous, vérifiez que vous la respectez
-bien, faites les modifications nécessaires.
+bien, faites les modifications nécessaires dans votre `Dockerfile`.
## Utilisez le fichier `.dockerignore`
diff --git a/tutorial/dockerfiles/interactive.md b/tutorial/dockerfiles/interactive.md
index e290485..886bfc9 100644
--- a/tutorial/dockerfiles/interactive.md
+++ b/tutorial/dockerfiles/interactive.md
@@ -38,23 +38,11 @@ Installons maintenant un programme :
```
-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 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` :
+Sauvegardez vos modifications en tant que nouvelle image Docker, avec
+la commande `commit` :
```
@@ -62,9 +50,11 @@ commencer directement de votre image avec `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` :
+en remplaçant `CONTAINER` par le nom ou l'identifiant du container qui
+doit servir de modèle. `my_nano` est le nom que vous voudrez utiliser
+à la place d'`ubuntu`.
+
+Testons sans plus attendre notre nouvelle image :
```
diff --git a/tutorial/dockerfiles/multistaged.md b/tutorial/dockerfiles/multistaged.md
deleted file mode 100644
index 55d144e..0000000
--- a/tutorial/dockerfiles/multistaged.md
+++ /dev/null
@@ -1,6 +0,0 @@
-\newpage
-
-Multi-stage build
-=================
-
-TODO
diff --git a/tutorial/dockerfiles/rendu.md b/tutorial/dockerfiles/rendu.md
index 89c375b..5ee8b2b 100644
--- a/tutorial/dockerfiles/rendu.md
+++ b/tutorial/dockerfiles/rendu.md
@@ -1,3 +1,56 @@
+\newpage
+
+Projet et rendu
+===============
+
+Projet
+------
+
+Avec l'aide d'un `Dockerfile` *multi-stage*, réalisez l'image la plus petite
+possible (partant d'un `FROM scratch`), qui permette d'utiliser la [page de
+compte à rebours](https://virli.nemunai.re/countdown.html) avec cette
+configuration pour nginx :
+
+```conf
+ events {}
+
+ http {
+ default_type text/html;
+
+ index countdown.html;
+
+ server {
+ listen 80;
+
+ root /srv/http;
+
+ rewrite "^/[0-9]+:[0-9]{2}$" /countdown.html;
+ rewrite "^/[0-9]+$" /countdown.html;
+ }
+ }
+```
+
+Vous pouvez envisager dans un premier temps d'extraire de l'image `nginx`, le
+binaire `nginx` lui-même et observer les différents problèmes. Vous pourrez
+ensuite par exemple envisager de compiler `nginx` (vous trouverez les sources
+du projet :
).
+
+Dans tous les cas, votre `Dockerfile` devra être facilement maintenable
+(notamment en cas de nouvelle version du serveur web), et vous devrez apporter
+une attention particulière au suivi des bonnes pratiques d'écriture des
+`Dockerfile`.
+
+### Exemple d'exécution
+
+
+```
+ 42sh$ docker build -t countdown countdown
+ 42sh$ docker run -d -P countdown
+ 42sh$ firefox http://localhost:32198/42:23
+```
+
+
+
Modalités de rendu
------------------
@@ -13,6 +66,9 @@ et exclusivement à celle-ci que vous devez envoyer vos rendus. Tout rendu
envoyé à une autre adresse et/ou non signé et/ou reçu après la correction ne
sera pas pris en compte.
+Par ailleurs, n'oubliez pas de répondre à
+[l'évaluation du cours](https://www.epitaf.fr/moodle/mod/quiz/view.php?id=215).
+
Tarball
-------
@@ -20,20 +76,23 @@ Tarball
Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...).
-Voici une arborescence type (vous pourriez avoir des fichiers supplémentaires,
-cela dépendra de votre avancée dans le projet) :
+Voici une arborescence type (vous pourriez avoir des fichiers
+supplémentaires) :
```
- login_x-TP1_5/influxdb/Dockerfile
- login_x-TP1_5/influxdb/influxdb.conf
- login_x-TP1_5/chronograf
- login_x-TP1_5/chronograf/Dockerfile
- login_x-TP1_5/chronograf/chronograf.conf
- login_x-TP1_5/mymonitoring
- login_x-TP1_5/mymonitoring/Dockerfile
- login_x-TP1_5/mymonitoring/chronograf.conf
- login_x-TP1_5/mymonitoring/influxdb.conf
- login_x-TP1_5/mymonitoring/supervisor.conf
+ login_x-TP2/
+ login_x-TP2/youp0m/
+ login_x-TP2/youp0m/Dockerfile
+ login_x-TP2/youp0m/entrypoint.sh
+ login_x-TP2/youp0m/.dockerignore
+ login_x-TP2/youp0m/...
+ login_x-TP2/countdown/Dockerfile
+ (login_x-TP2/countdown/nginx.conf)
+ (login_x-TP2/countdown/countdown.html)
```
+
+Les deux fichiers `nginx.conf` et `countdown.html` seront écrasés par
+les fichiers fournis lors de la correction, vous n'êtes pas donc
+obligés de les embarquer dans votre rendu.
diff --git a/tutorial/dockerfiles/split.md b/tutorial/dockerfiles/split.md
deleted file mode 100644
index 93648f9..0000000
--- a/tutorial/dockerfiles/split.md
+++ /dev/null
@@ -1,58 +0,0 @@
-\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
-```
-
diff --git a/tutorial/dockerfiles/supervisor.md b/tutorial/dockerfiles/supervisor.md
deleted file mode 100644
index f0d6b68..0000000
--- a/tutorial/dockerfiles/supervisor.md
+++ /dev/null
@@ -1,104 +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.6/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 : . 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 à :
-
-
-
-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`.