Tutorial 1 ready for 2023

This commit is contained in:
nemunaire 2022-09-13 23:19:59 +02:00
parent 1e4154f133
commit 885a410b77
26 changed files with 465 additions and 259 deletions

Binary file not shown.

View File

@ -1,18 +1,53 @@
include ../pandoc-opts.mk
SOURCES = tutorial.md \
../containers/overview.md \
../docker-basis/discover.md ../docker-basis/installation.md ../docker-basis/what.md ../docker-basis/first.md ../docker-basis/cleaning.md ../docker-basis/ex-flask.md \
../docker-basis/volumes.md \
../docker-basis/linking.md ../docker-basis/linking-ex-fic.md ../docker-basis/linking-ex-help.md \
../docker-advanced/what.md ../docker-advanced/setup.md ../docker-advanced/manual.md ../docker-advanced/compose.md \
../docker-advanced/security.md \
../docker-basis/ex-flask-volume.md \
../docker-basis/linking.md \
SOURCES_COURSE = tutorial.md \
../containers/overview.md \
../docker-basis/discover.md ../docker-basis/installation.md ../docker-basis/what.md ../docker-basis/first.md ../docker-basis/cleaning.md \
../docker-basis/volumes.md \
../docker-basis/linking.md \
SOURCES_TUTO = tutorial.md \
../header-tp.md \
../docker-basis/ex-flask.md \
../docker-basis/ex-flask-volume.md \
see-fun-for-more.md \
../new-page.md \
ex2.md \
../docker-basis/ex-owncloud.md ../docker-basis/linking-ex-help.md \
SOURCES_TUTOFUN = tutorial.md \
../header-tp-fun.md \
note-tp-fun.md \
../docker-basis/ex-flask.md \
../docker-basis/ex-flask-volume.md \
../docker-basis/ex-flask-s3.md \
../docker-basis/linking-ex-help.md \
SOURCES_PROJECT = tutorial.md \
../docker-advanced/what.md ../docker-advanced/setup.md ../docker-advanced/manual.md ../new-page.md ../docker-advanced/compose.md \
rendu.md
all: tutorial.pdf
all: course.pdf tutorial.pdf tutorial-fun.pdf project.pdf
tutorial.pdf: ${SOURCES}
course.pdf: ${SOURCES_COURSE}
pandoc ${PANDOCOPTS} -o $@ $+
tutorial.pdf: ${SOURCES_TUTO}
pandoc ${PANDOCOPTS} -o $@ $+
tutorial-fun.pdf: ${SOURCES_TUTOFUN}
pandoc ${PANDOCOPTS} -o $@ $+
project.pdf: ${SOURCES_PROJECT}
pandoc ${PANDOCOPTS} -o $@ $+
clean::
rm tutorial.pdf
rm -f course.pdf tutorial.pdf tutorial-fun.pdf project.pdf

2
tutorial/1/ex2.md Normal file
View File

@ -0,0 +1,2 @@
Mise en pratique des notions
----------------------------

View File

@ -0,0 +1,4 @@
Il s'agit d'une version du TP qui va un peu plus loin que le cours.
Si vous connaissez déjà bien Docker, vous pouvez pimenter encore davantage le
sujet en apprenant les subtilités de Podman, en l'utilisant la place de Docker.

View File

@ -11,140 +11,41 @@ monitoring, d'un simple :
<div lang="en-US">
```
42sh$ docker-compose up
42sh$ docker compose up
```
</div>
Vous intégrerez les trois images (`influxdb`, `chronograf` et `telegraf`),
Vous intégrerez les trois images (`influxdb`, `chronograf`[^onlyv1] et `telegraf`),
mettrez en place les *volumes* et *networks* nécessaires au bon fonctionnement
de la stack.
[^onlyv1]: N'ajoutez pas chronograf dans votre `docker-compose.yml` si vous
avez opté pour la version 2 d'InfluxDB.
Le résultat final attendu doit permettre d'afficher dans `chronograf` l'hôte
auto-monitoré par la stack, sans plus de configuration. Vous aurez pour cela
éventuellement besoin de placer des fichiers de configuration à côté de votre
besoin de placer des fichiers de configuration à côté de votre
`docker-compose.yml`, afin de pouvoir inclure ces configurations dans les
conteneurs, sans avoir besoin de reconstruire ces conteneurs.
Modalités de rendu
------------------
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP.
Un service automatique s'occupe de réceptionner vos rendus, de faire des
vérifications élémentaires 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é et/ou reçu après la correction ne
sera pas pris en compte.
En cas de doute, [une interface](https://virli.nemunai.re/rendus/) et une API
sont disponibles pour consulter l'état de votre rendu.
Par ailleurs, n'oubliez pas de répondre à
[l'évaluation du cours](https://virli.nemunai.re/quiz/11).
Tarball
Arborescence attendue
-------
Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...).
Tous les fichiers identifiés comme étant à rendre sont à placer dans un dépôt
Git privé, que vous partagerez avec [votre
professeur](https://gitlab.cri.epita.fr/nemunaire/).
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) :
<div lang="en-US">
```
login_x-TP1/
login_x-TP1/ficadmin-run.sh
login_x-TP1/docker-compose.yml
login_x-TP1/...
./
./docker-compose.yml
./... # Pour les fichiers de configuration
```
</div>
## Signature du rendu
Deux méthodes sont utilisables pour signer votre rendu :
* signature du courriel ;
* signature de la tarball.
Dans les deux cas, si vous n'en avez pas déjà une, vous devrez créer une clef
PGP à **votre nom et prénom**.
Pour valider la signature, il est nécessaire d'avoir reçu la clef publique
**séparément**. Vous avez le choix de l'uploader sur un serveur de clefs, soit
de me fournir votre clef en main propre, soit l'envoyer dans un courriel
distinct.
### Signature du courriel
Une version récente de [Thunderbird](https://www.thunderbird.net/fr/) vous
permettra d'envoyer des courriels signés. Si vous n'avez qu'une version
ancienne, l'extension [Enigmail](https://enigmail.net) est très bien réputée
pour signer ses mails depuis Thunderbird. Bien entendu, de nombreuses autres
solutions sont disponibles.
Utilisez le service automatique <signcheck@nemunai.re> pour savoir si votre
courriel est correctement signé et que je suis en mesure de vérifier la
signature.
### Astuces
#### No public key
Si vous recevez un rapport avec l'erreur suivante :
<div lang="en-US">
```
[FAIL] Bad signature. Here is the gnupg output:
gpg: Signature made Tue Jan 01 16:42:23 2014 CET
gpg: using RSA key 842807A84573CC96
gpg: requesting key E2CCD99DD37BD32E from hkp server keys.openpgp.org
gpg: Can't check signature: No public key
```
</div>
C'est que votre clef publique n'est pas dans mon trousseau et que les
méthodes de récupération automatique n'ont pas permis de la
trouver. Uploadez votre clef sur [un serveur de
clefs](https://keys.openpgp.org/) ou envoyez un courriel au service
avec votre clef publique en pièce jointe, avant de retenter votre
rendu.
#### Not explicit username
Si vous recevez un rapport avec l'erreur suivante :
<div lang="en-US">
```
[FAIL] The username of your key is not explicit, I can't find you.
```
</div>
Votre clef ne contient sans doute pas vos noms et prénoms ou l'adresse
électronique associée à la clef n'est pas celle que j'ai dans ma base de
données.
#### I've decided to skip your e-mail
Si vous recevez un rapport concluant ainsi :
<div lang="en-US">
```
After analyzing your e-mail, I've decided to SKIP it.
```
</div>
Cela signifie que la lecture de votre courriel qui a été préférée n'est pas
celle d'un rendu. Vérifiez que vous n'envoyez pas votre clef publique avec
votre rendu.
Votre rendu sera pris en compte en faisant un [tag **signé par votre clef
PGP**](https://lessons.nemunai.re/keys). Consultez les détails du rendu (nom du
tag, ...) sur la page dédiée au projet sur la plateforme de rendu.

View File

@ -0,0 +1,2 @@
Pour continuer à travailler sur youp0m, vous pouvez passer sur le TP fun. Il y
a encore bien d'autres méthodes pour gérer les fichiers, si ça vous intéresse.

View File

@ -3,22 +3,8 @@ title: Virtualisation légère -- TP n^o^ 1
subtitle: Les bases de Docker
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA
date: Jeudi 16 septembre 2021
date: Mercredi 7 septembre 2022
abstract: |
Durant ce premier TP, nous allons apprendre à utiliser Docker, puis
nous apprendrons à déployer un groupe de conteneurs !
\vspace{1em}
Le TP se termine par un petit projet à rendre à <virli@nemunai.re> au
plus tard le **mercredi 22 septembre 2021 à 23 h 42**. Consultez la
dernière section de chaque partie pour plus d'informations sur les
éléments à rendre. Et n'oubliez pas de répondre aux [questions de
cours](https://virli.nemunai.re/quiz/11).
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](https://keys.openpgp.org/search?q=nemunaire%40nemunai.re) faire signer
votre clef et n'hésitez pas à [faire signer la
vôtre](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
...

View File

@ -0,0 +1,15 @@
### Les conteneurs Docker
Alors que les images constituent la partie immuable de Docker, les conteneurs
sont sa partie vivante. Chaque conteneur est créé à partir d'une image: à
chaque fois que nous lançons un conteneur, une couche lecture/écriture est
ajoutée au-dessus de l'image. Cette couche est propre au conteneur et
temporaire: l'image n'est pas modifiée par l'exécution d'un conteneur.
![Couches d'un conteneur](layers-multi-container.png "Couches d'un conteneur"){ width=70% }
Chaque conteneur s'exécute dans un environnement restreint et distinct de
l'environnement principal (où vous avez votre bureau). Par exemple, dans cet
environnement, vous ne pouvez pas voir les processus qui sont situés en dehors,
ni accéder aux fichiers extérieurs.

View File

@ -0,0 +1,95 @@
L'écosystème des conteneurs
===========================
Pour entrer dans le monde des conteneurs, il faut bien saisir un certain nombre
de concepts qui ont vu le jour progressivement, au fil des tentatives faites
pour standardiser tout cet écosystème. Ce sont des notions importantes, car la
plupart des outils utilisent d'une manière ou d'une autre ces concepts.
Les images
----------
Une image est une méthode pour distribuer un logiciel, qui s'apparente à un
package. L'image contient les exécutables, mais aussi toutes les dépendances,
les bibliothèques systèmes, les fichiers de configuration,... Tout ce dont
notre logiciel a besoin pour fonctionner.
Il existe différentes typologies d'images:
- certaines contiennent des logiciels ou des services prêts à l'emploi: le
serveur web `nginx`, ou `apache`, ou encore la base de données MySQL, ou
MongoDB,...
- certaines contiennent un programme spécifique: on peut vouloir utiliser
`git`, le client `MySQL`, `emacs` ou bien encore le navigateur Chrome;
- d'autes enfin servent pour développer et étendre les possibilités. Ce sont
souvent des images utilisées comme bases pour les deux types que l'on a vus:
Debian, Alpine, Windows,...
Il est aisé de s'échanger des images, ainsi tout le monde peut récupérer des
images de ses logiciels favoris.
Les registres
-------------
Les registres sont des plateformes qui centralisent les images. Ils permettent
de récupérer les images, ils disposent généralement d'une interface permettant
de consulter leur catalogue, et ils permettent aussi d'en envoyer.
Les registres les plus connus sont le Docker Hub ou Quay.io. Ils contiennent à
la fois:
- des images officielles (`nginx`, `postgres`,...) issues directement de leurs
éditeurs,
- des images communautaires, maintenues par les utilisateurs d'un logiciel,
mais aussi,
- des images de tout un chacun pour ses propres besoins.
D'autres registres existent en dehors de ces grands noms publics. Certaines
forges telles que GitHub, GitLab ou Gitea proposent un service de registre que
leurs utilisateurs peuvent utiliser pour publier les images liées à un
projet. Cela permet aux utilisateurs de retrouver tous les produits de
compilation au même endroit.
Enfin, chacun peut déployer son propre registre, qui peut alors avoir des
droits d'accès restreint. Une entreprise peut vouloir déployer un registre
privé lorsqu'elle utilise des conteneurs dans son infrastructure, mais qu'il
n'est pas souhaitable que ses images soient diffusées.
Les conteneurs
--------------
On parle d'un conteneur pour désigner une instance en cours d'exécution.
Lorsqu'on lance un conteneur, une copie de l'image est créée sur le disque,
puis le système crée une isolation, pour contenir et restreindre l'exécution
aux seules données de l'image.
Les conteneurs sont par nature **immuables**: on exécute le contenu d'une
image déjà construite, on n'y change pas le code qui est exécuté et on n'y fait
pas de changements qui pourrait altérer son fonctionnement. L'idée directrice dans
le design des conteneurs est de toujours être en mesure de pouvoir relancer un
conteneur ailleurs et s'attendre exactement au même comportement.
Cela signifie que l'on ne fait par exemple pas de mise à jour dans un
conteneur: lorsque notre application ou le système sous-jacent a besoin d'être
mis à jour, on construit ou on télécharge une nouvelle image.
Ce qui distingue deux exécutions de la même image, ce sont les données que l'on
donne au conteneur.
::::: {.question}
##### Tous les conteneurs utilisent ces principes? {-}
Nous avons décrit ici les concepts propres aux conteneurs applicatifs. Dans le
cas des conteneurs systèmes, leurs cycles de vie sont plus proches de l'usage que
l'on peut avoir des machines virtuelles classiques: chaque conteneur démarre
avec son historique (la manière dont il a été installé, les mises à jour qui
ont été appliquées, les configurations modifiées et les données qui ont été
apportées au fil du temps ...). On ne peut pas dans ces circonstances
remplacer un conteneur système par un autre, tout comme on ne peut pas
remplacer une machine virtuelle que l'on a installée et configuré à la main.
:::::

View File

@ -1,5 +1,3 @@
\newpage
Composition de conteneurs
-------------------------
@ -42,7 +40,7 @@ fonctionnalités de Docker.
#### `services`
Cette section énumère la liste des services (ou conteneurs) qui seront gérés
par `docker-compose`.
par `docker compose`.
Ils 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
@ -144,9 +142,9 @@ la commande suivante et admirer le résultat:
<div lang="en-US">
```bash
docker-compose up
docker compose up
```
</div>
Encore une fois, testez la bonne connexion entre chronograf (accessible sur
<http://localhost:8888>) et influxdb.
Encore une fois, testez la bonne connexion entre `chronograf` (accessible sur
<http://localhost:8888>) et `influxdb`.

View File

@ -1,5 +1,3 @@
\newpage
Lier des conteneurs
-------------------
@ -16,7 +14,7 @@ Le premier conteneur qui doit être lancé est la base de données orientée sé
temporelles:
[InfluxDB](https://www.influxdata.com/time-series-platform/influxdb/).
En effet, tous les autres conteneurs ont besoin de cette base de données pour
fonctionner correctement\: il serait impossible à *Chronograf* d'afficher les
fonctionner correctement: il serait impossible à *Chronograf* d'afficher les
données sans base de données, tout comme *Telegraf* ne pourrait écrire les
métriques dans une base de données à l'arrêt.
@ -31,6 +29,16 @@ docker container run -p 8086:8086 -d --name mytsdb influxdb:1.8
```
</div>
::::: {.warning}
Remarquez que nous n'utilisons pas la version 2 d'InfluxDB. Sa mise en
place est plus contraignantes pour faire de simples tests. Si vous
souhaitez tout de même utiliser la dernière version de la stack TICK,
vous pouvez consulter le `README` du conteneur sur le Docker Hub:\
<https://hub.docker.com/_/influxdb>
:::::
Comme il s'agit d'une API REST, nous pouvons vérifier le bon fonctionnement de
notre base de données en appelant:
@ -59,8 +67,8 @@ le client officiel (le binaire s'appelle `influx`):
```
42sh$ docker container run --rm -it --link mytsdb:influxdb influxdb:1.8 \
influx -host influxdb
Connected to http://influxdb:8086 version 1.8.9
InfluxDB shell version: 1.8.9
Connected to http://influxdb:8086 version 1.8.10
InfluxDB shell version: 1.8.10
> show databases
name: databases
name
@ -132,7 +140,7 @@ système. Pour cela, on commence par télécharger *Telegraf*:
<div lang="en-US">
```bash
V=1.19.2
V=1.23.4
P=telegraf-${V}_linux_$(uname -m)
curl https://dl.influxdata.com/telegraf/releases/${P}.tar.gz | \
tar xzv -C /tmp
@ -163,7 +171,7 @@ Et observons ensuite:
```bash
42sh$ docker container run --rm -it --link mytsdb:zelda influxdb:1.8 \
influx -host zelda
InfluxDB shell version: 1.8.9
InfluxDB shell version: 1.8.10
> show databases
name: databases
name
@ -199,6 +207,16 @@ lancé, celui-ci va régulièrement envoyer des métriques de cette machine.
À vous de jouer pour lancer le conteneur
[*Chronograf*](https://store.docker.com/images/chronograf).
::::: {.question}
#### InfluxDB v2 {-}
Chronograf n'existe plus en tant que projet indépendant dans la version 2, si
vous êtes parti sur cette version, vous retrouverez les tableaux de bord
directement dans l'interface d'InfluxDB, sur le port 8086.
:::::
L'interface de *Chronograf* est disponible sur le port 8888.
Consultez la [documentation du conteneur](https://hub.docker.com/_/chronograf)

View File

@ -1,5 +1,3 @@
\newpage
Mise en place
-------------
@ -11,19 +9,7 @@ communauté, et parfois même appropriées par Docker.
### `docker-compose`
Dans cette partie, 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 (et en Python). Il constitue aujourd'hui une brique de
l'écosystème Docker, presque indispensable !
#### 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
Dans cette partie, nous allons avoir besoin du plugin `docker-compose`.
L'équipe en charge du projet met à disposition un exécutable que nous pouvons
téléchargeant depuis <https://github.com/docker/compose/releases>.
@ -31,6 +17,21 @@ téléchargeant depuis <https://github.com/docker/compose/releases>.
Ajoutez l'exécutable dans le dossier des plugins : `$HOME/.docker/cli-plugins`
(sans oublier de `chmod +x` !).
::::: {.more}
Autrefois, `docker-compose` était un script tiers que l'on utilisait
indépendamment de Docker. Le projet, historiquement écrit en Python, a été
entièrement réécrit récemment afin qu'il s'intégre mieux dans l'écosystème.
Vous trouverez encore de nombreux articles vous incitant à utiliser
`docker-compose`. Dans la plupart des cas, vous pouvez simplement remplacer par
des appels à `docker compose`.
Il y a même un outil qui a spécialement été conçu pour migrer les lignes de
commandes :\
<https://github.com/docker/compose-switch>
:::::
#### Vérification du fonctionnement
@ -39,8 +40,8 @@ Comme avec Docker, nous pouvons vérifier le bon fonctionnement de
<div lang="en-US">
```
42sh$ docker-compose --version
docker-compose version: 1.29.2
42sh$ docker compose version
Docker Compose version v2.10.2
```
</div>

View File

@ -3,12 +3,17 @@
Découvrons Docker
=================
Entrons sans plus attendre dans le vif du sujet: Docker.
Tous les programmes d'exécution de conteneurs (*container runtimes*) ne
fonctionnent pas de la même manière et n'apportent pas les mêmes
fonctionnalités. Dans leurs couches les plus basses, chacun de ces programmes
va certes utiliser les mêmes fonctionnalités du système d'exploitation afin de
créer les couches d'isolation, mais chacun apporte un enrobage et une manière
d'utiliser les conteneurs différents.
Ce projet, dont les sources ont été rendues libres en 2013, a tout de
suite remporté un engouement indéniable. Le projet a énormément grossi
depuis, et il s'est aussi bien stabilisé. Aujourd'hui de nombreuses
entreprises n'hésitent plus à l'utiliser en production.
Nous allons commencer sans plus attendre par découvrir Docker. Ce projet, dont
les sources ont été rendues libres en 2013, a tout de suite remporté un
engouement indéniable. Le projet a énormément grossi depuis, et il s'est aussi
bien stabilisé.
Dans ce chapitre, nous allons partir à la découverte de cet outil:
après l'avoir installé, nous apprendrons d'abord les concepts clefs puis

View File

@ -0,0 +1,91 @@
::::: {.exercice}
Faire persister les données à l'heure du cloud
----------------------------------------------
Aïe, c'est un sujet épineux... On peut entendre ici et là que les conteneurs
permettent de monter en puissance facilement, mais lorsque l'on est lié à un
espace de stockage classique, on se heurte bien vite à des réalités physiques.
Même si l'on utilise un système de fichiers partagé pour stocker nos images et
ainsi répartir la puissance de calcul entre plusieurs machines, il va vite
arriver un moment où la bande passante du disque réseau ne suivra plus. Il faut
donc passer sur une classe de stockage d'un autre type: l'Object Storage.
L'Object Storage est une méthode de stockage des objets adaptée au monde du
Cloud Computing. Il s'agit d'une API HTTP avec laquelle on peut interagir pour
accéder, ajouter, partager ou gérer un flot d'octets, que l'on nomme *objet* dans
le jargon, mais il s'agit ni plus ni moins que d'un fichier.
Il est de la responsabilité de l'administrateur du service (Amazon, Microsoft,
Google ...) de faire en sorte que les données soient suffisamment réparties
pour éviter les goulots d'étranglement et les SPOF. Ce n'est plus notre
problème de gérer la distribution de la bande passante, ni l'usure des disques,
ni même la capacité de notre espace de stockage.
Toutes les applications ne sont malheureusement pas nativement compatibles avec
ce système de stockage. Mais il se trouve que youp0m le supporte!
Nous allons déployer le service `minio`, qui est une implémentation libre de
l'API d'Amazon S3. `minio` dispose d'une interface graphique pour gérer nos
*buckets*, c'est un volume auquel on attribue des droits particuliers,
notamment quel utilisateur y a accès. C'est au sein d'un *bucket* que l'on va
pouvoir envoyer nos fichiers. Ceux-ci seront référencés avec une *clef*
(l'équivalent du chemin): il n'y a pas de notion d'arborescence ou de dossier,
mais par convention, lorsque l'on place un `/` dans le nom de la clef, on
considère qu'il s'agit d'un séparateur de dossier.
::::: {.question}
Comme il n'y a pas de notion de dossier, il n'y a pas besoin de créer
l'arborescence avant d'écrire un objet. Chaque objet est référencé par sa clef,
sans qu'il ne soit question d'arborescence ou de dossier.
À partir d'un *bucket* vide, vous pouvez donc directement ajouter le fichier:
`images/next/racoon.jpg`, sans vous préoccuper de l'existence ou non des
dossiers `images` et `next`, la séparation n'est qu'une convention, l'objet
n'est pas enregistré comme étant le fichier `racoon.jpg` du dossier `next`,
mais bien comme `images/next/racoon.jpg`.
:::::
Au sein de l'interface minio, vous devrez donc créer un bucket (par exemple
`youp0m` puisque ce sera un *bucket* dédié à cette application). Ainsi qu'un
compte de service (sous *Identity* > *Service Accounts*). Cela vous permettra
de récupérer une *Access Key* ainsi que sa *Secret Key* associée. Ce sont des
informations qui permettront au conteneur `youp0m` de s'identifier auprès de
l'API.
Il faudra ensuite lancer un conteneur youp0m avec les
options suivantes:
<div lang="en-US">
```
S3_ENDPOINT=http://NOM_DU_CONTENEUR_MINIO:9000
S3_BUCKET=NOM_DU_BUCKET
S3_ACCESS_KEY=ACCESS_KEY_GENEREE
S3_SECRET_KEY=SECRET_KEY_CORRESPONDANTE
S3_PATH_STYLE=true
```
</div>
::::: {.more}
La dernière option `S3_PATH_STYLE` est importante lorsque l'on utilise minio,
car il y a une subtile différence entre l'API d'Amazon et celle de minio
lorsque l'on ne le configure pas davantage.
Un *bucket* pour Amazon S3 correspond à un sous-domaine (par exemple
`youp0m.nemunai.re.s3.amazonaws.com.` pour le bucket
`youp0m.nemunai.re`). Cependant, dans notre installation de minio, nous n'avons
pas de nom de domaine à proprement parler. L'option est donc là pour indiquer
que le nom du *bucket* est attendu comme premier paramètre de l'URL et non pas
comme sous-domaine.
:::::
Votre instance de `youp0m` est désormais réellement prête pour passer en
production. Bravo!
:::::

View File

@ -0,0 +1,47 @@
::::: {.exercice}
Faire persister les données: niveau 1
--------------------------------------
Le service `youp0m` que nous avons déployé fonctionne comme on pourrait s'y
attendre, mais vous imaginez bien que ce n'est pas très pratique de devoir
réimporter les données à chaque fois que l'on met à jour le conteneur ou sa
configuration.
Maintenant que nous savons utiliser les volumes nous allons les utiliser pour
rendre notre service plus pérenne.
Le service stocke par défaut les images dans le dossier `/images` du
conteneur. Pour les sauvegarder hors du conteneur, nous devons donc créer un
volume vers ce dossier:
<div lang="en-US">
```
42sh$ docker volume create youp0m_images
42sh$ docker run -v youp0m-image:/images -p 8080:8080 registry.nemunai.re/youp0m
```
</div>
Ajoutons quelques images puis arrêtons et supprimons le conteneur. Relançons
ensuite un nouveau conteneur avec les mêmes options:
<div lang="en-US">
```
42sh$ docker run -v youp0m-image:/images -p 8080:8080 registry.nemunai.re/youp0m
```
</div>
::::: {.question}
Nous ne recréons pas le volume, il est important de ne pas l'avoir supprimé
ici, puisque c'est ce volume qui assure la persistance des images.
:::::
Nos images sont bien persistantes d'une instance à l'autre de notre contenu.
Nous voici prêt à déployer en production notre service, sans crainte de perdre
les jolies contributions. Mais... est-ce que ce sera suffisant pour répondre aux
milliers de visiteurs attendus?
:::::

View File

@ -1,5 +1,3 @@
\newpage
Mon premier webservice
----------------------
@ -14,7 +12,7 @@ Nous pouvons télécharger et lancer le service grâce à :
<div lang="en-US">
```bash
docker container run -i nemunaire/youp0m
docker container run -i registry.nemunai.re/youp0m
```
</div>
@ -37,7 +35,7 @@ Nous pouvons rediriger le port avec l'argument <span lang="en-US">`-p dst_host:s
<div lang="en-US">
```bash
docker container run -i -p 8080:8080 nemunaire/youp0m
docker container run -i -p 8080:8080 registry.nemunai.re/youp0m
```
</div>
@ -75,7 +73,7 @@ On utilise l'option `-d` pour lancer le conteneur en tâche de fond:
<div lang="en-US">
```bash
docker container run -d -p 8080:8080 nemunaire/youp0m
docker container run -d -p 8080:8080 registry.nemunai.re/youp0m
```
</div>
@ -98,11 +96,11 @@ absolument un clone de <https://food.p0m.fr/>!
Il s'agit du même service, mais ce ne sont pas les mêmes images.
On ne peut pas utiliser le même port sur la machine hôte, mais pour le reste,
il s'agit des mêmes options\:
il s'agit des mêmes options:
<div lang="en-US">
```bash
docker container run -d -p 8081:8080 nemunaire/youp0m
docker container run -d -p 8081:8080 registry.nemunai.re/youp0m
```
</div>
@ -141,7 +139,7 @@ Pour ajouter une variable d'environnement, cela se passe dans la commande
<div lang="en-US">
```bash
docker container run -e YOUP0M_PASSWORD=foobar -p 8080:8080 nemunaire/youp0m
docker container run -e YOUP0M_PASSWORD=foobar -p 8080:8080 registry.nemunai.re/youp0m
```
</div>

View File

@ -16,11 +16,11 @@ pare-feu (mais cette dernière partie n'est pas demandée, gardez simplement en
tête que cela doit pouvoir être fait manuellement au cas par cas: sur une
machine sans pare-feu configurée, cela ne demande pas d'étape supplémentaire).
Votre script devra se limiter aux notions vues durant cette partie du TP
(ie. sans utiliser `docker-compose` ou `docker stack` que l'on verra par la
suite). Il pourra cependant faire usage des commandes `docker OBJECT inspect`
pour ne pas avoir à faire d'analyse syntaxique sur les retours des commandes
lisibles par les humains.
Votre script devra se limiter aux notions vues durant cette partie (ie. sans
utiliser `docker-compose` ou `docker stack` que l'on verra par la suite). Il
pourra cependant faire usage des commandes `docker OBJECT inspect` pour ne pas
avoir à faire d'analyse syntaxique sur les retours des commandes lisibles par
les humains.
Cette instance devra utiliser une base de données MySQL (lancée par votre
script dans un autre conteneur) et contenir ses données dans un ou plusieurs
@ -46,3 +46,14 @@ http://localhost:12345/
</div>
:::::
### Au secours, ça veut pas se connecter!
Lorsque nous lançons pour la première fois notre conteneur MySQL ou MariaDB, un
script est chargé d'initialiser le volume attaché à `/var/lib/mysql`. Les
démarrages suivant, ou si vous réutilisez un volume déjà initialisé avec une
base de données, le script ne refait pas d'initialisation. Même si les
variables d'environnement ont changé.
Si vous rencontrez des difficultés pour connecter votre conteneur à
`my-db`, prenez le temps de recréer un volume.

View File

@ -1,5 +1,3 @@
\newpage
Mon premier conteneur
---------------------

View File

@ -52,13 +52,6 @@ distribution:
<https://docs.docker.com/engine/install/debian/>
::::: {.question}
**Et Kali Linux alors?** Kali étant basée sur Debian, référez-vous à
la procédure d'installation de cette distribution.
:::::
### Sous Windows et macOS
Bien que les fonctionnalités de contenerisation de Docker que nous utiliserons
@ -80,9 +73,9 @@ la machine virtuelle sous-jacente.
::::: {.warning}
Depuis septembre 2021, ces applications passent sous une licence payante pour
les grosses entreprises[^DockerSubscription]. Cela ne nous concerne pas, car la
licence est gratuite pour un usage éducatif ou personnel.
Depuis septembre 2021, ces applications sont passées sous une licence payante
pour les grosses entreprises[^DockerSubscription]. Cela ne vous concerne pas,
car la licence est gratuite pour un usage éducatif ou personnel.
Notez que cela ne concerne pas le projet ou le binaire Docker: ceux-ci restent
libres. Seules les applications Docker Desktop sont concernées.
@ -155,7 +148,7 @@ Server:
#### `no such file or directory`?
Si vous avez cette erreur: `dial unix /var/run/docker.sock: no such file or
directory.`, le deamon n'est sans doute pas lancé. Lancez-le:
directory.`, le daemon n'est sans doute pas lancé. Lancez-le:
<div lang="en-US">
```bash

View File

@ -1,15 +1,3 @@
### Au secours, ça veut pas se connecter!
Lorsque nous lançons pour la première fois notre conteneur MySQL ou MariaDB, un
script est chargé d'initialiser le volume attaché à `/var/lib/mysql`. Les
démarrages suivant, ou si vous réutilisez un volume déjà initialisé avec une
base de données, le script ne refait pas d'initialisation. Même si les
variables d'environnement ont changé.
Si vous rencontrez des difficultés pour connecter votre conteneur à
`my-db`, prenez le temps de recréer un volume.
### Entrer dans un conteneur en cours d'exécution
Dans certaines circonstances, les journaux ne sont pas suffisants pour déboguer

View File

@ -73,8 +73,7 @@ On pourra également faire de même avec un conteneur MySQL:
<div lang="en-US">
```bash
docker container run --name mydb -e MYSQL_ROOT_PASSWORD=my-secret-pw \
--mount source=prod_db,target=/var/lib/mysql\
mysql
--mount source=prod_db,target=/var/lib/mysql mysql
```
</div>
@ -88,7 +87,7 @@ Lorsque vous n'avez pas besoin de stocker les données et que vous ne désirez
pas qu'elles persistent (des données sensibles par exemple) ou si cela peut
améliorer les performances de votre conteneur, il est possible de créer des
points de montages utilisant le système de fichiers `tmpfs` et donc résidant
exclusivement en RAM\:
exclusivement en RAM:
<div lang="en-US">
```bash

View File

@ -1,40 +1,56 @@
\newpage
Composition de Docker
---------------------
Docker est un écosystème d'outils de haut niveau, permettant d'utiliser des
*conteneurs*.
Docker est une suite d'outils de haut niveau, permettant d'utiliser des
*conteneurs*. Le projet en lui-même utilise de nombreuses dépendances,
originellement développées par l'entreprise Docker Inc., puis laissé dans le
domaine public lors des efforts de standardisation en 2015.
Docker est composé d'un daemon lancé au démarrage de votre machine, avec lequel
vous interagissez via un client (le programme `docker`). La communication entre
le daemon et le client s'effectuant sur une API REST généralement au travers
d'une socket.
Commençons par planter le décor, en détaillant les principes de base de Docker.
Le client peut d'ailleurs ne pas être sur la même machine qui exécutera
### Séparation des compétences
Le projet s'article autour d'un daemon lancé au démarrage de la machine, avec
lequel on interagit via un client (le programme `docker`). La communication
entre le daemon et le client s'effectuant sur une API REST généralement au
travers d'une socket.
::::: {.more}
Tous les programmes d'exécution de conteneurs n'utilisent pas une architecture
avec un daemon et un client. `podman` que l'on peut généralement substituer à
Docker n'emploie pas de daemon. Chaque utilisateur de la machine peut donc
disposer de ses propres conteneurs, sans interférer avec ceux de ses voisins.
D'un point de vue de la sécurité, le daemon Docker est exécuté en tant que
super-utilisateur. C'est sur ce daemon que repose la sécurité de la machine, ce
qui peut être beaucoup de responsabilité. Gardez en tête que le modèle
d'exécution de Docker n'est pas unique. Nous avons le choix.
:::::
Le processus client peut d'ailleurs ne pas être sur la même machine qui exécute
effectivement les conteneurs.[^dockermachine]
C'est ce qu'il se passe lorsqu'on utilise *Docker4Windows* ou *Docker4Mac*:
C'est ce qu'il se passe lorsqu'on utilise Docker sur Windows ou macOS:
une machine virtuelle Linux est lancée parallèlement au système de base et
chaque commande `docker` tapée est passée au deamon dans la machine virtuelle.
chaque commande `docker` tapée est passée au daemon dans la machine virtuelle.
[^dockermachine]: Il suffit de modifier la variable d'environnement
`DOCKER_HOST` ou de passer le paramètre `-H` suivi de l'URL de la socket à
`docker`. Voir aussi: <https://docs.docker.com/machine/overview/>
Commençons par planter le décor, en détaillant les principaux mécanismes de
Docker.
### Les images Docker
Une image Docker est un système de fichiers en lecture seule. Elle est formée
d'un ensemble de couches, agrégées selon le principe d'UnionFS.
Comme nous l'avons vu en introduction, les images sont un moyen de récupérer
facilement un environnement d'exécution complet, prêt à l'emploi. Une image
Docker donc est un système de fichiers en lecture seule.
Une image peut, par exemple, contenir:
* un système Ubuntu opérationnel,
* le programme `busybox`,
* un serveur web et votre application web, prêts à l'emploi,
* votre site web personnel, prêt à l'emploi,
* ...
Les images sont utilisées comme **modèle** qui sera ensuite dupliqué à chaque
@ -43,36 +59,34 @@ fois que l'on démarrera un nouveau conteneur.
Il y a deux méthodes pour obtenir des images Docker: soit les construire avec
les outils fournis, soit les récupérer depuis un registre.
### Les registres Docker (*Docker registries*)
Les registres sont des plates-formes de stockage, publiques ou privées,
contenant des images. Ils permettent de récupérer des images, mais également
d'en envoyer.
Le registre utilisé de base est le [Docker Hub](https://hub.docker.com/): il
contient à la fois des images officielles (ubuntu, debian, nginx, ...), des
images créées par des utilisateurs, mais aussi des images de grands éditeurs,
payantes, à destination des entreprises.
Des registres alternatifs existent comme celui de [quay.io](https://quay.io/search),
et les dépôts de sources tels que
[GitHub](https://github.blog/2020-09-01-introducing-github-container-registry/)
et [GitLab](https://docs.gitlab.com/ee/user/packages/container_registry/) le
proposent également.
Lorsque vous ne précisez pas l'adresse d'un registre, Docker va aller chercher
sur le [Docker Hub](https://hub.docker.com/). C'est son registre par défaut, chaque
### Les conteneurs Docker
### Les plugins Docker
Alors que les images constituent la partie immuable de Docker, les conteneurs
sont sa partie vivante. Chaque conteneur est créé à partir d'une image: à
chaque fois que nous lançons un conteneur, une couche lecture/écriture est
ajoutée au-dessus de l'image. Cette couche est propre au conteneur et
temporaire: l'image n'est pas modifiée par l'exécution d'un conteneur.
L'architecture de Docker est devenue très modulable. Le projet est parti dans
de nombreuses directions, chacun voulant tirer la couverture vers soit, et
l'équipe maintenant le projet a parfois eu du mal à arbitrer les bonnes choses
à ajouter ou non au projet.
![Couches d'un conteneur](layers-multi-container.png "Couches d'un conteneur"){ width=70% }
Afin de palier aux besoins complémentaires, parfois accessoires, parfois
salvateurs, un système de plugins a été intégré. Il permet d'appeler d'autres
programmes comme s'il s'agissait de composant de Docker.
Chaque conteneur s'exécute dans un environnement restreint et distinct de
l'environnement principal (où vous avez votre bureau). Par exemple, dans cet
environnement, vous ne pouvez pas voir les processus qui sont situés en dehors,
ni accéder aux fichiers extérieurs.
Certains plugins ajoutent des options à la ligne de commande (`docker-compose`,
`docker-scan`, `docker-buildx` ...). D'autres ajoutent des typologies de
réseaux, de gestion du stockage ou ajoutent de l'authentification.
Pour ajouter un plugin à Docker, il suffit de l'ajouter dans un sous-dossier de
`/usr/lib/docker/cli-plugins` pour qu'il soit accessible à tous les
utilisateurs de notre machine ou dans `$HOME/.docker/` si l'on veut l'installer
seulement pour nous.
Par exemple, les plugins ajoutant des commandes iront dans
`$HOME/.docker/cli-plugins`. Par exemple, si l'on souhaite pouvoir disposer de
la commande `docker compose`, on téléchargera le plugin vers l'emplacement:
`$HOME/.docker/cli-plugins/docker-compose`.
Plus récemment, de nouveaux plugins ont vu le jour et se basent directement sur
des conteneurs que l'on peut télécharger depuis un registre d'images.

View File

@ -71,7 +71,7 @@ fichiers.
##### Utilisation avec Docker {-}
Nous avons déjà évoqué le fait que le deamon pouvait ne pas se trouver sur la
Nous avons déjà évoqué le fait que le daemon pouvait ne pas se trouver sur la
même machine que le client `docker`. Eh bien avec `docker-machine` cela prend
tout son sens, car vous pouvez très facilement changer de daemon/machine avec
une simple commande :

View File

@ -0,0 +1,2 @@
Exercices et travaux pratiques (version fun !)
==============================

2
tutorial/header-tp.md Normal file
View File

@ -0,0 +1,2 @@
Exercices et travaux pratiques
==============================

1
tutorial/new-page.md Normal file
View File

@ -0,0 +1 @@
\newpage