Save tuto corrections

This commit is contained in:
nemunaire 2022-02-24 20:43:43 +01:00
parent f5ee6b8534
commit 10448a6c8d
115 changed files with 1425 additions and 1291 deletions

View file

@ -3,7 +3,7 @@ include ../pandoc-opts.mk
SOURCES = tutorial.md \ SOURCES = tutorial.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/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/volumes.md \
../docker-basis/linking.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/what.md ../docker-advanced/setup.md ../docker-advanced/manual.md ../docker-advanced/compose.md \
../docker-advanced/security.md \ ../docker-advanced/security.md \
rendu.md rendu.md

View file

@ -6,7 +6,7 @@ institute: EPITA
date: Jeudi 16 septembre 2021 date: Jeudi 16 septembre 2021
abstract: | abstract: |
Durant ce premier TP, nous allons apprendre à utiliser Docker, puis Durant ce premier TP, nous allons apprendre à utiliser Docker, puis
nous apprendrons à déployer un groupe de conteneurs ! nous apprendrons à déployer un groupe de conteneurs !
\vspace{1em} \vspace{1em}

View file

@ -3,7 +3,7 @@
Rendu Rendu
===== =====
Est attendu d'ici le TP suivant : Est attendu d'ici le TP suivant :
- le rendu des exercice de ce TP ; - le rendu des exercice de ce TP ;
- vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/12). - vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/12).
@ -41,7 +41,7 @@ Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...). placer dans une tarball (pas d'archive ZIP, RAR, ...).
Voici une arborescence type (vous pourriez avoir des fichiers Voici une arborescence type (vous pourriez avoir des fichiers
supplémentaires) : supplémentaires) :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -7,7 +7,7 @@ date: Jeudi 23 septembre 2021
abstract: | abstract: |
Durant ce deuxième TP, nous allons voir comment créer nos propres Durant ce deuxième TP, nous allons voir comment créer nos propres
images, et comment s'assurer qu'elles n'ont pas de vulnérabilités images, et comment s'assurer qu'elles n'ont pas de vulnérabilités
connues ! connues !
\vspace{1em} \vspace{1em}

View file

@ -35,7 +35,7 @@ On trouve par exemple :
Pour émettre un ping, il est nécessaire d'envoyer des paquets ICMP. À la Pour émettre un ping, il est nécessaire d'envoyer des paquets ICMP. À la
différence des datagrammes UDP ou des segments TCP, il n'est pas forcément différence des datagrammes UDP ou des segments TCP, il n'est pas forcément
simple d'envoyer des paquets ICMP lorsque l'on est simple utilisateur, car simple d'envoyer des paquets ICMP lorsque l'on est simple utilisateur, car
l'usage du protocole ICMP dans une socket est restreint : il faut soit être l'usage du protocole ICMP dans une soket est restreint : il faut soit être
super-utilisateur, soit que le noyau ait été configuré pour autoriser certains super-utilisateur, soit que le noyau ait été configuré pour autoriser certains
utilisateurs à envoyer des `ECHO_REQUEST`. utilisateurs à envoyer des `ECHO_REQUEST`.
@ -64,7 +64,7 @@ se mettent à fournir par défaut une configuration qui permette de se passer de
*capabilities* pour lancer `ping`.\ *capabilities* pour lancer `ping`.\
Si vous vous rendez compte que votre binaire `ping` est dans ce cas, testez Si vous vous rendez compte que votre binaire `ping` est dans ce cas, testez
depuis un conteneur, par exemple : depuis un conteneur, par exemple :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -83,7 +83,7 @@ depuis un conteneur, par exemple :
</div> </div>
Dans le conteneur le binaire `ping` est *setuid root*, vous pouvez faire des Dans le conteneur le binaire `ping` est *setuid root*, vous pouvez faire des
tests en retirant le *setuid* : tests en retirant le *setuid* :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -94,7 +94,7 @@ tests en retirant le *setuid* :
``` ```
</div> </div>
Puis en ajoutant la *capability* : Puis en ajoutant la *capability* :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -1,12 +1,12 @@
### Exercice (obligatoire pour les SRS -- optionnel pour les GISTRE) ### Exercice (obligatoire pour les SRS -- optionnel pour les GISTRE)
Poursuivons [notre script de monitoring](#script-monitoring) afin d'envoyer nos Poursuivons [notre script de monitoring](#script-monitoring) afin d'envoyer nos
résultats vers InfluxDB : nous l'appellerons `./telegraf.sh` résultats vers InfluxDB : nous l'appellerons `./telegraf.sh`.
#### Rappel d'InfluxDB\ #### Rappel d'InfluxDB\
Commençons par lancer le conteneur Docker d'InfluxDB (pour éviter de Commençons par lancer le conteneur Docker d'InfluxDB (pour éviter de
l'installer sur notre machine) : l'installer sur notre machine) :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -16,7 +16,7 @@ docker container run --name mytsdb -d -p 8086:8086 influxdb:1.8
Il nous faut ensuite créer une base de données pour y stocker nos Il nous faut ensuite créer une base de données pour y stocker nos
métriques. Voici comment on s'était débrouillé précédemment pour interagir avec métriques. Voici comment on s'était débrouillé précédemment pour interagir avec
InfluxDB : InfluxDB :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -33,7 +33,7 @@ Vérifiez que la base de données `metrics` a bien été créée.
#### Monitoring vers InfluxDB\ #### Monitoring vers InfluxDB\
Maintenant, envoyons nos données vers la base Maintenant, envoyons nos données vers la base
<https://docs.influxdata.com/influxdb/v1.8/guides/write_data/> : <https://docs.influxdata.com/influxdb/v1.8/guides/write_data/> :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -43,7 +43,7 @@ curl -i -XPOST 'http://localhost:8086/write?db=metrics' --data-binary \
</div> </div>
Pour vérifier que les données ont bien été ajoutées, nous pouvons effectuer la Pour vérifier que les données ont bien été ajoutées, nous pouvons effectuer la
requête suivante dans notre client `influx` : requête suivante dans notre client `influx` :
<div lang="en-US"> <div lang="en-US">
```sql ```sql
@ -54,15 +54,15 @@ SELECT * from "$my_cgroup_name";
#### Monitorer davantage de données\ #### Monitorer davantage de données\
Liste non exhaustive de données à monitorer : Liste non exhaustive de données à monitorer :
* Nombre d'IOs effectué ; * Nombre d'IOs effectué ;
* nombre d'octets lus/écrits sur les disques ; * nobre d'octets lus/écrits sur les disques ;
* temps de calcul utilisé (`userspace`, `system`, tout confondu) ; * temps de calcul utilisé (`userspace`, `system`, tout confondu) ;
* ... * ...
Tous les cgroups existants dans le dernier noyau publié ont leur documentation Tous les cgroups existants dans le dernier noyau publié ont leur documentation
accessible ici : accessible ici :
- v1 : <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/index.html> - v1 : <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/index.html>
- v2 : <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html> - v2 : <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>

View file

@ -4,40 +4,40 @@ Les *cgroup*s
------------- -------------
Les *cgroup*s (pour *Control Group*s) permettent de collecter des statistiques Les *cgroup*s (pour *Control Group*s) permettent de collecter des statistiques
sur des **groupes de processus** (voire même, des threads !) et de leur sur des **groupes de processus** (voire même, des threads !) et de leur
attribuer des propriétés. Il est par exemple possible de leur imposer des attribuer des propriétés. Il est par exemple possible de leur imposer des
limites d'utilisation de ressources ou d'altérer leur comportement : quantité limites d'utilisation de ressources ou d'altérer leur comportement : quantité
de RAM, temps CPU, bande passante, ... de RAM, temps CPU, bande passante, ...
Apparue dès [Linux Apparue dès [Linux
2.6.24](https://kernelnewbies.org/Linux_2_6_24#Task_Control_Groups) 2.6.24](https://kernelnewbies.org/Linux_2_6_24#Task_Control_Groups)
(en 2008 !), les *cgroup*s sont répartis en différents sous-systèmes (en 2008 !), les *cgroup*s sont répartis en différents sous-systèmes
(*subsystem*), chacun étant responsable d'un type de ressources (*subsystem*), chacun étant responsable d'un type de ressources
spécifique : spécifique :
- [`blkio` (`io` dans la v2) - [`blkio` (`io` dans la v2)
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/blkio-controller.html) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/blkio-controller.html)
limites et statistiques de bande passante sur les disques ; limites et statistiques de bande passante sur les disques ;
- `cpu` : cycles CPU minimum garantis ; - `cpu` : cycles CPU minimum garantis ;
- [`cpuacct` (inclus dans `cpu` dans la v2) - [`cpuacct` (inclus dans `cpu` dans la v2)
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpuacct.html) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpuacct.html)
statistiques du temps CPU utilisé ; statistiques du temps CPU utilisé ;
- [`cpuset` - [`cpuset`
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpusets.html) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpusets.html)
associe des tâches à un/des CPU particuliers (par exemple pour dédier un cœur associe des tâches à un/des CPU particuliers (par exemple pour dédier un cœur
du CPU à un programme, qui ne pourra alors utiliser que ce CPU et pas les du CPU à un programme, qui ne pourra alors utiliser que ce CPU et pas les
autres) ; autres) ;
- [`devices` - [`devices`
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/devices.html) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/devices.html)
règles de contrôle de création (`mknod`) et d'accès aux périphériques ; règles de contrôle de création (`mknod`) et d'accès aux périphériques ;
- [`freezer` - [`freezer`
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/freezer-subsystem.html) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/freezer-subsystem.html)
pour suspendre et reprendre l'exécution d'un groupe de tâches ; pour suspendre et reprendre l'exécution d'un groupe de tâches ;
- [`hugetlb` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/hugetlb.html) statistiques et limitation de l'usage de la fonctionnalité `HugeTLB` (permettant d'obtenir des pages mémoires plus grande que 4 kB) ; - [`hugetlb` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/hugetlb.html) statistiques et limitation de l'usage de la fonctionnalité `HugeTLB` (permettant d'obtenir des pages mémoires plus grande que 4 kB) ;
- [`memory` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/memory.html) statistiques et limitation d'usage de la mémoire vive et de la *swap* ; - [`memory` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/memory.html) statistiques et limitation d'usage de la mémoire vive et de la *swap* ;
- [`net_cls` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_cls.html) applique un `classid` à tous les paquets émis par les tâches du *cgroup*, pour filtrage par le pare-feu en sortie ; - [`net_cls` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_cls.html) applique un `classid` à tous les paquets émis par les tâches du *cgroup*, pour filtrage par le pare-feu en sortie ;
- [`net_prio` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_prio.html) surcharge la valeur de l'option de priorité `SO_PRIORITY`, ordonant la file d'attente des paquets sortants ; - [`net_prio` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_prio.html) surcharge la valeur de l'option de priorité `SO_PRIORITY`, ordonant la file d'attente des paquets sortants ;
- [`pids` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/pids.html) statistiques et limitation du nombre de processus ; - [`pids` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/pids.html) statistiques et limitation du nombre de processus ;
- ... - ...
Nous allons commencer par faire quelques tests avec le *cgroup* *freezer*, qui Nous allons commencer par faire quelques tests avec le *cgroup* *freezer*, qui
@ -48,19 +48,19 @@ lorsqu'on le décide.
### Montage du *freezer* ### Montage du *freezer*
En fonction de la configuration de votre système, vous allez vous trouver dans En fonction de la configuration de votre système, vous allez vous trouver dans
l'une de ces trois situations : l'une de ces trois situations :
- Votre dossier `/sys/fs/cgroup` contient à la fois des fichiers `cgroup.*` et - Votre dossier `/sys/fs/cgroup` contient à la fois des fichiers `cgroup.*` et
éventuellement des dossiers : vous avez une distribution moderne qui utilise éventuellement des dossiers : vous avez une distribution moderne qui utilise
la nouvelle version des `cgroup`s. la nouvelle version des `cgroup`s.
- Votre dossier `/sys/fs/cgroup` contient d'autres dossiers au nom des - Votre dossier `/sys/fs/cgroup` contient d'autres dossiers au nom des
sous-systèmes que l'on a listé ci-dessus : il s'agit des `cgroup`s v1. sous-systèmes que l'on a listé ci-dessus : il s'agit des `cgroup`s v1.
- Votre dossier `/sys/fs/cgroup` est vide ou inexistant, vous pouvez choisir - Votre dossier `/sys/fs/cgroup` est vide ou inexistant, vous pouvez choisir
d'utiliser la version de votre choix : d'utiliser la version de votre choix :
Pour utiliser la v1 : Pour utiliser la v1 :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -70,7 +70,7 @@ l'une de ces trois situations :
</div> </div>
Pour utiliser la v2 : Pour utiliser la v2 :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -103,7 +103,7 @@ La première étape dans l'utilisation d'un *cgroup* est donc de créer un group
Pour ce faire, il suffit de créer un nouveau dossier dans un groupe existant, Pour ce faire, il suffit de créer un nouveau dossier dans un groupe existant,
par exemple la racine. par exemple la racine.
On commence par se rendre à la racine : On commence par se rendre à la racine :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -112,7 +112,7 @@ cd /sys/fs/cgroup/ # v2
``` ```
</div> </div>
Puis on crée notre groupe : Puis on crée notre groupe :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -134,7 +134,7 @@ version, vous allez devoir activer le ou les contrôleurs dont vous avez besoin
sous-système que l'on voulait). sous-système que l'on voulait).
Pour activer le contrôleur *memory* dans notre groupe `virli`, nous utilisons Pour activer le contrôleur *memory* dans notre groupe `virli`, nous utilisons
la commande suivante : la commande suivante :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -163,9 +163,9 @@ le fichier `cgroup.procs` de notre groupe. Ce fichier contient la liste des
processus rattachés à notre *cgroup*. processus rattachés à notre *cgroup*.
Ouvrons un nouveau terminal (c'est lui que l'on va geler), et récupérons son Ouvrons un nouveau terminal (c'est lui que l'on va geler), et récupérons son
PID : `echo $$`. PID : `echo $$`.
Pour ajouter une tâche à ce groupe, cela se passe de cette manière : Pour ajouter une tâche à ce groupe, cela se passe de cette manière :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -190,7 +190,7 @@ adaptés.
En affichant le contenu du dossier `virli`, nous pouvions constater que En affichant le contenu du dossier `virli`, nous pouvions constater que
celui-ci contenait déjà un certain nombre de fichiers. Certains d'entre-eux celui-ci contenait déjà un certain nombre de fichiers. Certains d'entre-eux
sont en lecture seule et permettent de lire des statistiques instantanées sur sont en lecture seule et permettent de lire des statistiques instantanées sur
le groupe ; tandis que d'autres sont des propriétés que nous pouvons modifier. le groupe ; tandis que d'autres sont des propriétés que nous pouvons modifier.
Nous pouvons consulter l'état de gel du groupe en affichant le contenu du Nous pouvons consulter l'état de gel du groupe en affichant le contenu du
fichier\ fichier\
@ -204,7 +204,7 @@ consultez
### Changement d'état ### Changement d'état
Faisons exécuter à notre interpréteur une commande pour voir effectivement Faisons exécuter à notre interpréteur une commande pour voir effectivement
l'exécution s'arrêter. Si vous manquez d'inspiration, utilisez : l'exécution s'arrêter. Si vous manquez d'inspiration, utilisez :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -213,7 +213,7 @@ for i in $(seq 9999); do echo -n $i; sleep .1; echo -n " - "; sleep .1; done
</div> </div>
Maintenant, nous avons donné l'ordre au noyau de ne plus allouer de temps de Maintenant, nous avons donné l'ordre au noyau de ne plus allouer de temps de
calcul à notre shell et ses fils : calcul à notre shell et ses fils :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -223,7 +223,7 @@ echo 1 > /sys/fs/cgroup/virli/cgroup.freeze # v2
</div> </div>
À cet instant, vous devriez voir votre compteur s'arrêter. Pour reprendre À cet instant, vous devriez voir votre compteur s'arrêter. Pour reprendre
l'exécution : l'exécution :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -233,7 +233,7 @@ echo 0 > /sys/fs/cgroup/virli/cgroup.freeze # v2
</div> </div>
### Exercice : script de monitoring {- #script-monitoring} ### Exercice : script de monitoring {- #script-monitoring}
À nous maintenant de concevoir un script qui va enregistrer vers une base de À nous maintenant de concevoir un script qui va enregistrer vers une base de
données des statistiques issues des *cgroup*s, tel `telegraf`. données des statistiques issues des *cgroup*s, tel `telegraf`.
@ -267,7 +267,7 @@ doit cependant être possible d'y trouver des statistiques intéressantes, dont
la quantité de mémoire utilisée. Ici nous affichons au début le PID du la quantité de mémoire utilisée. Ici nous affichons au début le PID du
processus, ce qui peut simplifier le débogage du script.\ processus, ce qui peut simplifier le débogage du script.\
Il s'utilise de la manière suivante : Il s'utilise de la manière suivante :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -275,7 +275,7 @@ Il s'utilise de la manière suivante :
``` ```
</div> </div>
:  :
- `group_name` correspond au nom du/des *cgroup*(s) à créer/rejoindre. - `group_name` correspond au nom du/des *cgroup*(s) à créer/rejoindre.
- `prog [args [...]]` est la commande que l'on souhaite monitorer, à exécuter - `prog [args [...]]` est la commande que l'on souhaite monitorer, à exécuter
@ -297,7 +297,7 @@ quantité de ressources mises à disposition à un groupe de processus.
Pour définir une limite, nous allons écrire la valeur dans le fichier Pour définir une limite, nous allons écrire la valeur dans le fichier
correspondant à une valeur limite, comme par exemple correspondant à une valeur limite, comme par exemple
`memory.max_usage_in_bytes`/`memory.max`, qui limite le nombre d'octets que `memory.max_usage_in_bytes`/`memory.max`, qui limite le nombre d'octets que
notre groupe de processus va pouvoir allouer au maximum : notre groupe de processus va pouvoir allouer au maximum :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -330,7 +330,7 @@ limiteurs, n'hésitez pas à consulter la documentation associée à chaque
*cgroup*. *cgroup*.
Mettez à jour votre script de monitoring pour prendre en compte les Mettez à jour votre script de monitoring pour prendre en compte les
limites que vous avez définies : limites que vous avez définies :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -352,5 +352,5 @@ limites que vous avez définies :
### Pour aller plus loin {-} ### Pour aller plus loin {-}
Pour tout connaître en détails, [la série d'articles de Neil Brown sur les Pour tout connaître en détails, [la série d'articles de Neil Brown sur les
Control groups](https://lwn.net/Articles/604609/) est excellente ! Plus [cet Control groups](https://lwn.net/Articles/604609/) est excellente ! Plus [cet
article sur la version 2](https://lwn.net/Articles/679786/). article sur la version 2](https://lwn.net/Articles/679786/).

View file

@ -1,4 +1,4 @@
L'isolation ... à 1  ? L'isolation ... à 1  ?
----------------------- -----------------------
Depuis les premières versions d'Unix, il est possible de changer le répertoire Depuis les premières versions d'Unix, il est possible de changer le répertoire
@ -83,7 +83,7 @@ pacstrap newroot/
</div> </div>
Dans les deux cas, nous nous retrouvons avec un dossier `newroot` contenant une Dans les deux cas, nous nous retrouvons avec un dossier `newroot` contenant une
distribution complète minimale, dans laquelle nous pouvons entrer : distribution complète minimale, dans laquelle nous pouvons entrer :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -100,9 +100,10 @@ sous forme de tarball :
#### Gentoo\ #### Gentoo\
<http://gentoo.mirrors.ovh.net/gentoo-distfiles/releases/amd64/autobuilds/current-stage3-amd64-openrc/stage3-amd64-openrc-20211128T170532Z.tar.xz>
<div lang="en-US"> <div lang="en-US">
```bash ```bash
wget http://gentoo.mirrors.ovh.net/gentoo-distfiles/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20210630T214504Z.tar.xz
tar xpf stage3-amd64-*.tar.xz -C newroot/ tar xpf stage3-amd64-*.tar.xz -C newroot/
``` ```
</div> </div>
@ -113,7 +114,7 @@ environnement qui tient dans 200 MB.
::::: :::::
Comme pour les autres distributions vues précédemment, nous pouvons entrer dans Comme pour les autres distributions vues précédemment, nous pouvons entrer dans
notre nouvelle racine comme ceci : notre nouvelle racine comme ceci :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -124,15 +125,16 @@ chroot newroot/ bash
#### Alpine\ #### Alpine\
<https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-minirootfs-3.14.2-x86_64.tar.gz>
<div lang="en-US"> <div lang="en-US">
```bash ```bash
wget https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-minirootfs-3.14.2-x86_64.tar.gz
tar xpf alpine-minirootfs-*.tar.xz -C newroot/ tar xpf alpine-minirootfs-*.tar.xz -C newroot/
``` ```
</div> </div>
Alpine se contentant de Busybox pour son système de base, nous n'avons pas Alpine se contentant de Busybox pour son système de base, nous n'avons pas
`bash`, mais on peut tout de même lancer `ash` : `bash`, mais on peut tout de même lancer `ash` :
<div lang="en-US"> <div lang="en-US">
```bash ```bash

View file

@ -8,5 +8,5 @@ allons tâcher d'apprendre comment il fonctionne en nous penchant sur un certain
nombre de fonctionnalités de Linux. nombre de fonctionnalités de Linux.
Dans un premier temps, nous allons aborder la manière dont le noyau Linux Dans un premier temps, nous allons aborder la manière dont le noyau Linux
permet de contrôler les processus : que ce soit en collectant des informations permet de contrôler les processus : que ce soit en collectant des informations
sur eux ou en imposant certaines restrictions. sur eux ou en imposant certaines restrictions.

View file

@ -3,7 +3,7 @@
Gestion de la mémoire Gestion de la mémoire
===================== =====================
Linux a une gestion de la mémoire bien particulière[^vm-overcommit] : par Linux a une gestion de la mémoire bien particulière[^vm-overcommit] : par
défaut, `malloc(3)` ne retournera jamais `NULL`. En se basant sur l'euristique défaut, `malloc(3)` ne retournera jamais `NULL`. En se basant sur l'euristique
qu'un bloc mémoire demandé ne sera pas utilisé directement et que de nombreux qu'un bloc mémoire demandé ne sera pas utilisé directement et que de nombreux
process ne feront pas un usage total des blocks qu'ils ont alloués, le noyau process ne feront pas un usage total des blocks qu'ils ont alloués, le noyau
@ -22,7 +22,7 @@ est-ce `init` qui est en train de gérer le lancement d'un nouveau daemon). On
dit alors que le noyau est *Out-Of-Memory*. dit alors que le noyau est *Out-Of-Memory*.
Pour se sortir d'une telle situation, et après avoir tenté de vider les caches, Pour se sortir d'une telle situation, et après avoir tenté de vider les caches,
il lance son arme ultime, pour retrouver au plus vite de la mémoire : il lance son arme ultime pour retrouver au plus vite de la mémoire :
l'*Out-Of-Memory killer*. l'*Out-Of-Memory killer*.
@ -39,7 +39,7 @@ jusqu'à ce que le système retrouve sa sérénité.
[^oom-algo]: <https://linux-mm.org/OOM_Killer> [^oom-algo]: <https://linux-mm.org/OOM_Killer>
## Esquiver l'OOM killer ? ## Esquiver l'OOM killer ?
Au sein d'un *cgroup* *memory*, les fichiers `memory.oom_control` (v1) ou Au sein d'un *cgroup* *memory*, les fichiers `memory.oom_control` (v1) ou
`memory.events` (v2) peuvent être utilisé afin de recevoir une notification du `memory.events` (v2) peuvent être utilisé afin de recevoir une notification du
@ -58,4 +58,4 @@ ce sujet.
Continuons l'exercice précédent où nous avions [fixé les Continuons l'exercice précédent où nous avions [fixé les
limites](#Fixer-des-limites) de mémoire que pouvez réserver les processus de limites](#Fixer-des-limites) de mémoire que pouvez réserver les processus de
notre groupe. Que se passe-t-il alors si `memhog` dépasse la quantité de notre groupe. Que se passe-t-il alors si `memhog` dépasse la quantité de
mémoire autorisée dans le `cgroup` ? mémoire autorisée dans le `cgroup` ?

View file

@ -1 +0,0 @@
../../subject/2/project-part1.md

115
tutorial/3/project-body.md Normal file
View file

@ -0,0 +1,115 @@
## Palier 1 : Restreindre l'environnement (2 points) {-}
Après avoir mis en place les bases de votre programme, commencez par créer les
différentes hiérarchies (si vous avez un noyau récent, vous pouvez utiliser les
cgroups-v2) dont vous allez avoir besoin pour limiter l'utilisation de
ressources.
Puis, mettez en place ces limites :
* pas plus d'1 GB de mémoire utilisée ;
* 1 seul CPU au maximum ;
* 100 PIDs ;
* ...
En bonus, vous pouvez gérer les cas où le noyau sur lequel s'exécute votre
moulinette ne possède pas tous ces *CGroup*s, au lieu de planter, ne rien faire
n'est pas forcément une mauvaise solution.
## Palier 2 : Réduire les `capabilities` (2 points) {-}
Réduisez au maximum les *capabilities*, de telle sorte qu'il ne soit pas
possible de faire un ping dans l'environnement restreint :
<div lang="en-US">
```
42sh# ping 9.9.9.9
PING 9.9.9.9 (9.9.9.9) 56(84) bytes of data.
64 bytes from 9.9.9.9: icmp_seq=1 ttl=56 time=3.93 ms
64 bytes from 9.9.9.9: icmp_seq=2 ttl=56 time=3.97 ms
^C
--- 9.9.9.9 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 3.931/3.954/3.978/0.067 ms
42sh# ./mymoulette /bin/bash
bash# curl http://www.linuxcontainers.org/ | md5sum
c7d68d1cb4737125a84cd69f55add202
bash# ping 9.9.9.9
ping: icmp open socket: Permission denied
```
</div>
**Astuces\ :** `prctl(2)`, `capabilities(7)`, `capget(2)`, `capset(2)`, ...
Aidez-vous du visualisateur de *capabilities* de la partie 1.3 du TP, pour voir
si vous êtes sur la bonne voie.
Si votre distribution vous permet d'utiliser `ping` sans privilège, utilisez à
la place n'importe quel binaire ayant besoin de *capabilities* pour vos tests,
par exemple `arping` (qui nécessite `CAP_NET_RAW`) ou `halt` (qui nécessite
`CAP_SYS_BOOT`) :
<div lang="en-US">
```
42sh# ./mymoulette /bin/bash
bash# arping 192.168.0.1
arping: socket: Permission denied
bash# halt -f
halt: (null): Operation not permitted
```
</div>
## Palier bonus : Utilisable par un utilisateur (2 points) {-}
Jouez avec les attributs étendus pour qu'un utilisateur non-privilégié puisse
exécuter votre moulinette. Ajoutez la/les commande(s) à votre `Makefile` ou
script d'installation.
## Création d'un environnement d'exécution minimal {-}
Plutôt que d'utiliser votre système hôte au complet, avec tous ses programmes
et toutes ses bibliothèques, il faudrait utiliser un système contenant le
strict minimum. Recréez un environnement minimaliste, comme on a pu en voir
dans la partie sur les `chroot`.
**Ne mettez pas cet environnement dans votre tarball de rendu, il vous
sera seulement utile pour faire des tests.**
## Palier 3 : Isolation du pauvre (1 point) {-}
Nous n'avons pas encore vu de meilleure méthode pour mieux isoler
l'environnement que de faire un `chroot`, ajoutez à votre programme cette
isolation rudimentaire. Et rendez-vous au prochain cours pour avoir une
meilleure isolation !
<div lang="en-US">
```
42sh$ which firefox
/usr/bin/firefox
42sh# ./mymoulette ./newrootfs/ /bin/bash
bash# which firefox
which: no firefox in (/usr/bin:/usr/local/bin:/bin:/opt/bin)
```
</div>
## Palier 4 : seccomp (2 points) {-}
Filtrez les appels système de telle sorte qu'aucun programme exécuté dans
votre bac à sable ne puisse plus lancer les appels systèmes suivants :
* `nfsservctl(2)` ;
* `personality(2)` ;
* `pivot_root(2)` ;
* ...
N'hésitez pas à en utiliser d'autres pour vos tests ;)
**Astuces\ :** `seccomp(2)`, `seccomp_init(3)`, `seccomp_load(3)`, ...

View file

@ -6,7 +6,7 @@ Projet et rendu
## Sujet ## Sujet
Vous allez commencer aujourd'hui un projet qui s'étendra au prochain TP et qui Vous allez commencer aujourd'hui un projet qui s'étendra au prochain TP et qui
consistera à réaliser la partie d'isolation de la moulinette des ACUs ! consistera à réaliser la partie d'isolation de la moulinette des ACUs !
Cette semaine, il faudra faire en sorte de restreindre un groupe de processus Cette semaine, il faudra faire en sorte de restreindre un groupe de processus
pour qu'il ne puisse pas faire de déni de service sur notre machine. pour qu'il ne puisse pas faire de déni de service sur notre machine.
@ -14,11 +14,11 @@ pour qu'il ne puisse pas faire de déni de service sur notre machine.
Il n'y a pas de restriction sur le langage utilisé, vous pouvez tout aussi bien Il n'y a pas de restriction sur le langage utilisé, vous pouvez tout aussi bien
utiliser du C, du C++, du Python, etc. utiliser du C, du C++, du Python, etc.
L'usage de bibliothèques **non relatives** au projet est autorisé : le but de L'usage de bibliothèques **non relatives** au projet est autorisé : le but de
ce sujet est d'évaluer votre compréhension et votre utilisation de la ce sujet est d'évaluer votre compréhension et votre utilisation de la
tuyauterie bas-niveau du noyau liée à la virtualisation légère. À partir du tuyauterie bas-niveau du noyau liée à la virtualisation légère. À partir du
moment où vous n'utilisez pas une bibliothèque qui abstrait complètement cette moment où vous n'utilisez pas une bibliothèque qui abstrait complètement cette
plomberie, n'hésitez pas à l'utiliser ! plomberie, n'hésitez pas à l'utiliser !
Gardez en tête que ce projet sera à continuer au prochain TP, où il sera Gardez en tête que ce projet sera à continuer au prochain TP, où il sera
principalement question de faire des appels systèmes. principalement question de faire des appels systèmes.

View file

@ -3,7 +3,7 @@
Rendu Rendu
===== =====
Est attendu d'ici le TP suivant : Est attendu d'ici le TP suivant :
- le rendu des exercice de ce TP ; - le rendu des exercice de ce TP ;
- vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/14). - vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/14).
@ -40,7 +40,7 @@ placer dans une tarball (pas d'archive ZIP, RAR, ...).
Voici une arborescence type (adaptez les extensions et les éventuels Voici une arborescence type (adaptez les extensions et les éventuels
fichiers supplémentaires associés au langage que vous aurez choisi fichiers supplémentaires associés au langage que vous aurez choisi
pour chaque exercice) : pour chaque exercice) :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -41,13 +41,13 @@ apporter des modifications.
Linux emploie de nombreux systèmes de fichiers virtuels : Linux emploie de nombreux systèmes de fichiers virtuels :
- `/proc` : contient, principalement, la liste des processus (`top` et ses - `/proc` : contient, principalement, la liste des processus (`top` et ses
dérivés se contentent de lire les fichiers de ce point de montage) ; dérivés se contentent de lire les fichiers de ce point de montage) ;
- `/proc/sys` : contient la configuration du noyau ; - `/proc/sys` : contient la configuration du noyau ;
- `/sys` : contient des informations à propos du matériel (utilisées notamment - `/sys` : contient des informations à propos du matériel (utilisées notamment
par `udev` pour peupler `/dev`) et des périphériques (taille des tampons, par `udev` pour peupler `/dev`) et des périphériques (taille des tampons,
clignottement des DELs, ...) ; clignottement des DELs, ...) ;
- `/sys/firmware/efi/efivars` : pour accéder et modifier les variables de - `/sys/firmware/efi/efivars` : pour accéder et modifier les variables de
l'UEFI ; l'UEFI ;
- ... - ...
Tous ces systèmes de fichiers sont généralement exclusivement stockés en Tous ces systèmes de fichiers sont généralement exclusivement stockés en
@ -130,7 +130,7 @@ uts:[4026531838]
Explorons le pseudo système de fichiers `/sys` pour écrire un script Explorons le pseudo système de fichiers `/sys` pour écrire un script
qui va, en fonction de ce que vous avez de disponible : qui va, en fonction de ce que vous avez de disponible :
* afficher des statistiques sur notre batterie ; * afficher des statistiques sur notre batterie ;
* afficher des statistiques la fréquence du CPU. * afficher des statistiques la fréquence du CPU.
##### `batinfo.sh`\ ##### `batinfo.sh`\
@ -194,7 +194,7 @@ Maintenant que vous savez lire des informations dans `/sys`, tentons d'aller
modifier le comportement de notre système. Au choix, réalisez l'un des scripts modifier le comportement de notre système. Au choix, réalisez l'un des scripts
suivants, en fonction du matériel dont vous disposez : suivants, en fonction du matériel dont vous disposez :
* inverser l'état des diodes de notre clavier ; * inverser l'état des diodes de notre clavier ;
* mettre en veille votre machine, en ayant programmé une heure de réveil. * mettre en veille votre machine, en ayant programmé une heure de réveil.
##### `rev_kdb_leds.sh`\ ##### `rev_kdb_leds.sh`\
@ -203,7 +203,7 @@ Si vous avez :
* numlock On, * numlock On,
* capslock Off, * capslock Off,
* scrolllock Off ; * scrolllock Off ;
Après avoir exécuté le script, nous devrions avoir : Après avoir exécuté le script, nous devrions avoir :
@ -242,7 +242,8 @@ Voici un exemple d'utilisation :
</div> </div>
Vous aurez besoin de définir une alarme au niveau de votre RTC, via le Vous aurez besoin de définir une alarme au niveau de votre RTC, via le
fichier : `/sys/class/rtc/rtcX/wakealarm`. fichier :\
`/sys/class/rtc/rtcX/wakealarm`
::::: {.warning} ::::: {.warning}
Attention au fuseau horaire utilisé par votre RTC, si votre système principal Attention au fuseau horaire utilisé par votre RTC, si votre système principal

View file

@ -12,13 +12,13 @@ particulier peut être renvoyé au programme.
Depuis la version 3.17 du noyau, l'appel système `seccomp(2)` permet de faire Depuis la version 3.17 du noyau, l'appel système `seccomp(2)` permet de faire
entrer le processus courant dans ce mode. En effet, c'est le processus lui-même entrer le processus courant dans ce mode. En effet, c'est le processus lui-même
qui déclare au noyau qu'il peut désormais se contenter d'une liste réduite qui déclare au noyau qu'il peut désormais se contenter d'une liste réduite
d'appels système ; à l'inverse des politiques de sécurité comme SELinux ou d'appels système ; à l'inverse des politiques de sécurité comme SELinux ou
AppArmor, qui encapsulent les programmes pour toute la durée de leur exécution. AppArmor, qui encapsulent les programmes pour toute la durée de leur exécution.
*Seccomp* est particulièrement utile lorsqu'un processus a terminé son *Seccomp* est particulièrement utile lorsqu'un processus a terminé son
initialisation (ne dépendant en général pas de données sujettes à initialisation (ne dépendant en général pas de données sujettes à
l'exploitation de vulnérabilité) et doit commencer à entrer dans des portions l'exploitation de vulnérabilité) et doit commencer à entrer dans des portions
de code promptes aux vulnérabilités : c'est notamment le cas des moteurs de de code promptes aux vulnérabilités : c'est notamment le cas des moteurs de
rendus des navigateurs Firefox et Chrome. rendus des navigateurs Firefox et Chrome.
@ -39,7 +39,7 @@ des appels système `read(2)`, `write(2)` (sur les descripteurs de fichier déj
ouvert), `_exit(2)` et `sigreturn(2)`. ouvert), `_exit(2)` et `sigreturn(2)`.
Historiquement, avant la création de l'appel système `seccomp(2)`, on activait Historiquement, avant la création de l'appel système `seccomp(2)`, on activait
ce mode via : ce mode via :
<div lang="en-US"> <div lang="en-US">
```c ```c
@ -63,7 +63,7 @@ auquel est appliqué un filtre `seccomp`, héritent également de ce filtre.
La construction de ce filtre est faite de manière programmatique, via La construction de ce filtre est faite de manière programmatique, via
des règles BPF (`Berkeley Packet Filter`). On passe ensuite ce filtre BPF en des règles BPF (`Berkeley Packet Filter`). On passe ensuite ce filtre BPF en
argument de l'appel système : argument de l'appel système :
<div lang="en-US"> <div lang="en-US">
```c ```c
@ -79,7 +79,7 @@ seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
### Exercice {-} ### Exercice {-}
Écrivez un programme filtrant un appel système, à l'aide de `seccomp` : Écrivez un programme filtrant un appel système, à l'aide de `seccomp` :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -1,6 +1,6 @@
\newpage \newpage
### Exercice : comparaison de *namespace* -- `cmpns.sh` ### Exercice : comparaison de *namespace* -- `cmpns.sh`
Les *namespaces* d'un programme sont exposés sous forme de liens symboliques Les *namespaces* d'un programme sont exposés sous forme de liens symboliques
dans le répertoire `/proc/<PID>/ns/`. dans le répertoire `/proc/<PID>/ns/`.
@ -46,9 +46,9 @@ que l'on cherche à comparer.
Ici, `self` fait référence au processus actuellement exécuté (comme il existe Ici, `self` fait référence au processus actuellement exécuté (comme il existe
un dossier `/proc/self/`, vous n'avez pas besoin de gérer de cas particulier un dossier `/proc/self/`, vous n'avez pas besoin de gérer de cas particulier
pour ça !). pour ça !).
Et pourquoi pas : Et pourquoi pas :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -1,19 +1,19 @@
\newpage \newpage
Exercice : `docker exec` Exercice : `docker exec`
------------------------ ------------------------
Après voir lu la partie concernant les *namespaces*, vous avez dû comprendre Après voir lu la partie concernant les *namespaces*, vous avez dû comprendre
qu'un `docker exec`, n'était donc rien de plus qu'un `nsenter(1)`. qu'un `docker exec`, n'était donc rien de plus qu'un `nsenter(1)`.
Réécrivons, en quelques lignes, la commande `docker exec` ! Réécrivons, en quelques lignes, la commande `docker exec` !
Pour savoir si vous avez réussi, comparez les sorties des commandes : Pour savoir si vous avez réussi, comparez les sorties des commandes :
- `ip address` ; - `ip address` ;
- `hostname` ; - `hostname` ;
- `mount` ; - `mount` ;
- `pa -aux` ; - `ps -aux` ;
- ... - ...
@ -27,11 +27,11 @@ d63ceae863956f8312aca60b7a57fbcc1fdf679ae4c90c5d9455405005d4980a
234269 234269
42sh# ./mydocker_exec mywebserver ip address 42sh# ./mydocker_exec mywebserver ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group def
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever valid_lft forever preferred_lft forever
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP group def
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.1/16 scope global eth0 inet 172.17.0.1/16 scope global eth0
valid_lft forever preferred_lft forever valid_lft forever preferred_lft forever

View file

@ -33,7 +33,7 @@ En fonction des options qui lui sont passées, `unshare(1)` va créer le/les
nouveaux *namespaces* et placer le processus dedans. nouveaux *namespaces* et placer le processus dedans.
Par exemple, nous pouvons modifier sans crainte le nom de notre machine, si Par exemple, nous pouvons modifier sans crainte le nom de notre machine, si
nous sommes passés dans un autre *namespace* `UTS` : nous sommes passés dans un autre *namespace* `UTS` :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -64,7 +64,7 @@ Ce *syscall*, propre à Linux, crée habituellement un nouveau processus (mais
aussi des threads) enfant de notre processus courant, comme `fork(2)` (qui lui aussi des threads) enfant de notre processus courant, comme `fork(2)` (qui lui
est un appel système POSIX) mais prend en plus de nombreux est un appel système POSIX) mais prend en plus de nombreux
paramètres. L'isolement ou non du processus se fait en fonction des *flags* qui paramètres. L'isolement ou non du processus se fait en fonction des *flags* qui
sont passés : sont passés :
* `CLONE_NEWNS`, * `CLONE_NEWNS`,
* `CLONE_NEWUTS`, * `CLONE_NEWUTS`,
@ -83,7 +83,7 @@ que nous verrons plus tard.
Pour créer un nouveau processus qui sera à la fois dans un nouvel espace de Pour créer un nouveau processus qui sera à la fois dans un nouvel espace de
noms réseau et dans un nouveau *namespace* `cgroup`, on écrirait un code C noms réseau et dans un nouveau *namespace* `cgroup`, on écrirait un code C
semblable à : semblable à :
<div lang="en-US"> <div lang="en-US">
```c ```c
@ -118,7 +118,7 @@ dans un nouvel espace de noms. Dans ce cas, on utilisera l'appel système
::::: {.warning} ::::: {.warning}
Le comportement de `unshare(2)` (ou `unshare(3)`) avec les *namespace*s *PID* Le comportement de `unshare(2)` (ou `unshare(3)`) avec les *namespace*s *PID*
et *Time* n'est pas celui que l'on peut attendre ! et *Time* n'est pas celui que l'on peut attendre !
En effet, après avoir appelé `unshare`, le processus reste tout de même dans En effet, après avoir appelé `unshare`, le processus reste tout de même dans
son *namespace* *Time* ou *PID* d'origine, seuls ses enfants (après un appel à son *namespace* *Time* ou *PID* d'origine, seuls ses enfants (après un appel à

View file

@ -22,12 +22,12 @@ Les espaces de noms du noyau, que l'on appelle *namespaces*, permettent de
dupliquer certaines structures, habituellement considérées uniques pour le dupliquer certaines structures, habituellement considérées uniques pour le
noyau, dans le but de les isoler d'un groupe de processus à un autre. noyau, dans le but de les isoler d'un groupe de processus à un autre.
On en dénombre huit (le dernier ayant été ajouté dans Linux 5.6) : `cgroup`, On en dénombre huit (le dernier ayant été ajouté dans Linux 5.6) : `cgroup`,
`IPC`, `network`, `mount`, `PID`, `time`, `user` et `UTS`. `IPC`, `network`, `mount`, `PID`, `time`, `user` et `UTS`.
La notion d'espace de noms est relativement nouvelle et a été intégrée La notion d'espace de noms est relativement nouvelle et a été intégrée
progressivement au sein du noyau Linux. Aussi, toutes les structures ne sont progressivement au sein du noyau Linux. Aussi, toutes les structures ne sont
pas encore *containerisables* : le document fondateur[^NSDOC] parle ainsi pas encore *containerisables* : le document fondateur[^NSDOC] parle ainsi
d'isoler les journaux d'événements ou encore les modules de sécurité (LSM, tels d'isoler les journaux d'événements ou encore les modules de sécurité (LSM, tels
que AppArmor, SELinux, Yama, ...). que AppArmor, SELinux, Yama, ...).
@ -74,12 +74,12 @@ Cet espace de noms isole la liste des processus et virtualise leurs numéros.
Une fois dans un espace, le processus ne voit que le sous-arbre de processus Une fois dans un espace, le processus ne voit que le sous-arbre de processus
également attachés à son espace. Il s'agit d'un sous-ensemble de l'arbre global également attachés à son espace. Il s'agit d'un sous-ensemble de l'arbre global
de PID : les processus de tous les PID *namespaces* apparaissent donc dans de PID : les processus de tous les PID *namespaces* apparaissent donc dans
l'arbre initial. l'arbre initial.
Pour chaque nouvel espace de noms de processus, une nouvelle numérotation est Pour chaque nouvel espace de noms de processus, une nouvelle numérotation est
initiée. Ainsi, le premier processus de cet espace porte le numéro 1 et aura initiée. Ainsi, le premier processus de cet espace porte le numéro 1 et aura
les mêmes propriétés que le processus `init` usuel\ ; entre autres, si un les mêmes propriétés que le processus `init` usuel\ ; entre autres, si un
processus est rendu orphelin dans ce *namespace*, il devient un fils de ce processus est rendu orphelin dans ce *namespace*, il devient un fils de ce
processus, et non un fils de l'`init` de l'arbre global. processus, et non un fils de l'`init` de l'arbre global.
@ -89,7 +89,7 @@ processus, et non un fils de l'`init` de l'arbre global.
Depuis Linux 2.6.29. Depuis Linux 2.6.29.
Cet espace de noms fournit une isolation pour toutes les ressources associées Cet espace de noms fournit une isolation pour toutes les ressources associées
aux réseaux : les interfaces, les piles protocolaires IPv4 et IPv6, les tables aux réseaux : les interfaces, les piles protocolaires IPv4 et IPv6, les tables
de routage, règles pare-feu, ports numérotés, etc. de routage, règles pare-feu, ports numérotés, etc.
Une interface réseau (`eth0`, `wlan0`, ...) ne peut se trouver que dans un seul Une interface réseau (`eth0`, `wlan0`, ...) ne peut se trouver que dans un seul
@ -126,7 +126,7 @@ correspond en fait à un sous-groupe de l'arborescence globale.
Ainsi, un processus dans un *CGroup* *namespace* ne peut pas voir le contenu Ainsi, un processus dans un *CGroup* *namespace* ne peut pas voir le contenu
des sous-groupes parents (pouvant laisser fuiter des informations sur le reste des sous-groupes parents (pouvant laisser fuiter des informations sur le reste
du système). Cela peut également permettre de faciliter la migration de du système). Cela peut également permettre de faciliter la migration de
processus (d'un système à un autre) : l'arborescence des *cgroups* n'a alors processus (d'un système à un autre) : l'arborescence des *cgroups* n'a alors
plus d'importance car le processus ne voit que son groupe. plus d'importance car le processus ne voit que son groupe.

View file

@ -11,7 +11,7 @@ de processus qui l'utilisent. C'est-à-dire que, la plupart du temps, le
termine. termine.
Lorsque l'on a besoin de référencer un *namespace* (par exemple pour le faire Lorsque l'on a besoin de référencer un *namespace* (par exemple pour le faire
persister après le dernier processus), on peut utiliser un `mount bind` : persister après le dernier processus), on peut utiliser un `mount bind` :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -29,7 +29,7 @@ obtenir un descripteur de fichier valide vers le *namespace* (pour passer à
::::: {.question} ::::: {.question}
#### Faire persister un *namespace* ? {-} #### Faire persister un *namespace* ? {-}
\ \
Il n'est pas possible de faire persister un espace de noms d'un reboot à Il n'est pas possible de faire persister un espace de noms d'un reboot à

View file

@ -6,7 +6,7 @@ Le *namespace* `mount`
L'espace de noms `mount` permet d'isoler la vision du système de fichiers L'espace de noms `mount` permet d'isoler la vision du système de fichiers
qu'ont un processus et ses fils. qu'ont un processus et ses fils.
Peut-être que l'on peut trouver avec ça, un moyen de faire un `chroot` plus sûr ? Peut-être que l'on peut trouver avec ça, un moyen de faire un `chroot` plus sûr ?
::::: {.warning} ::::: {.warning}
Attention il convient de prendre garde aux types de liaison existant entre vos Attention il convient de prendre garde aux types de liaison existant entre vos
@ -33,7 +33,7 @@ Nous allons essayer de changer la racine de notre système de fichier. À la
différence d'un `chroot(2)`, changer de racine est quelque chose d'un peu plus différence d'un `chroot(2)`, changer de racine est quelque chose d'un peu plus
sportif car il s'agit de ne plus avoir aucune trace de l'ancienne racine. Au sportif car il s'agit de ne plus avoir aucune trace de l'ancienne racine. Au
moins ici, il ne sera certainement pas possible de revenir en arrière dans moins ici, il ne sera certainement pas possible de revenir en arrière dans
l'arborescence\ ! l'arborescence !
Pour l'instant, votre système utilise sans doute la partition d'un disque Pour l'instant, votre système utilise sans doute la partition d'un disque
physique comme racine de son système de fichier. Le changement de racine, va physique comme racine de son système de fichier. Le changement de racine, va
@ -52,7 +52,7 @@ la racine d'un point de montage, comme l'explique `pivot_root(2)`. En effet, il
serait encore possible hypothétiquement de remonter dans l'arborescence si l'on serait encore possible hypothétiquement de remonter dans l'arborescence si l'on
ne se trouvait pas à la racine d'une partition au moment du basculement. ne se trouvait pas à la racine d'une partition au moment du basculement.
Si vous n'avez pas de partition à disposition, vous pouvez utiliser un `tmpfs` : Si vous n'avez pas de partition à disposition, vous pouvez utiliser un `tmpfs` :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -61,32 +61,31 @@ Si vous n'avez pas de partition à disposition, vous pouvez utiliser un `tmpfs`
``` ```
</div> </div>
Placez ensuite dans cette nouvelle racine le système de votre choix (cf. le TP Placez ensuite dans cette nouvelle racine le système de votre choix.
précédent pour les différentes méthodes et liens).
### Exercice : Changer de racine -- `myswitch_root.sh` ### Exercice : Changer de racine -- `myswitch_root.sh`
Voici les grandes étapes du changement de racine : Voici les grandes étapes du changement de racine :
1. S'isoler dans les *namespaces* adéquats ; 1. S'isoler dans les *namespaces* adéquats ;
2. Démonter ou déplacer toutes les partitions de l'ancienne racine vers la 2. Démonter ou déplacer toutes les partitions de l'ancienne racine vers la
nouvelle racine ; nouvelle racine ;
3. `pivot_root` ! 3. `pivot_root` !
#### S'isoler\ #### S'isoler\
Notre but étant de démonter toutes les partitions superflues, nous allons Notre but étant de démonter toutes les partitions superflues, nous allons
devoir nous isoler sur : devoir nous isoler sur :
* les points de montages, ça semble évident ; * les points de montages, ça semble évident ;
* les PIDs : car on ne pourra pas démonter une partition en cours * les PIDs : car on ne pourra pas démonter une partition en cours
d'utilisation. S'il n'y a pas de processus, il n'y a personne pour nous d'utilisation. S'il n'y a pas de processus, il n'y a personne pour nous
empêcher de démonter une partition ! empêcher de démonter une partition !
* les autres *namespaces* ne sont pas forcément nécessaires. * les autres *namespaces* ne sont pas forcément nécessaires.
Isolons-nous : Isolons-nous :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -97,12 +96,12 @@ Isolons-nous :
#### Dissocier la propagation des démontages\ #### Dissocier la propagation des démontages\
Attention ! avant de pouvoir commencer à démonter les partitions, il faut Attention ! avant de pouvoir commencer à démonter les partitions, il faut
s'assurer que les démontages ne se propagent pas via une politique de *shared s'assurer que les démontages ne se propagent pas via une politique de *shared
mount*. mount*.
Commençons donc par étiqueter tous nos points de montage (de ce *namespace*), Commençons donc par étiqueter tous nos points de montage (de ce *namespace*),
comme esclaves : comme esclaves :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -111,15 +110,15 @@ comme esclaves :
</div> </div>
#### Démonter tout !\ #### Démonter tout !\
À vous maintenant de démonter vos points d'attache. Il ne devrait vous rester À vous maintenant de démonter vos points d'attache. Il ne devrait vous rester
après cette étape que : `/`, `/dev`, `/sys`, `/proc`, `/run` et leurs fils. après cette étape que : `/`, `/dev`, `/sys`, `/proc`, `/run` et leurs fils.
#### Switch !\ #### Switch !\
À ce stade, dans votre console, vous avez plusieurs solutions : utiliser À ce stade, dans votre console, vous avez plusieurs solutions : utiliser
`switch_root(8)` ou `pivot_root(8)`. La première abstrait plus de choses que la `switch_root(8)` ou `pivot_root(8)`. La première abstrait plus de choses que la
seconde. seconde.
@ -136,7 +135,7 @@ Cette commande, plus proche du fonctionnement de l'appel système
`pivot_root(2)`, requiert de notre part que nous ayons préalablement déplacé `pivot_root(2)`, requiert de notre part que nous ayons préalablement déplacé
les partitions systèmes à leur place dans la nouvelle racine. les partitions systèmes à leur place dans la nouvelle racine.
L'appel de la commande sert à intervertir les deux racines ; elle prend en argument : L'appel de la commande sert à intervertir les deux racines ; elle prend en argument :
* le chemin de la nouvelle racine, * le chemin de la nouvelle racine,
* le chemin dans la nouvelle racine où placer l'ancienne. * le chemin dans la nouvelle racine où placer l'ancienne.
@ -144,7 +143,7 @@ L'appel de la commande sert à intervertir les deux racines ; elle prend en argu
Une fois le pivot effectué, on peut démonter l'ancienne racine. Une fois le pivot effectué, on peut démonter l'ancienne racine.
Pour lancer la première commande dans la nouvelle racine, on passe généralement Pour lancer la première commande dans la nouvelle racine, on passe généralement
par : par :
<div lang="en-US"> <div lang="en-US">
```bash ```bash

View file

@ -4,7 +4,7 @@ Je vous recommande la lecture du *man* `namespaces(7)` introduisant et
énumérant les *namespaces*. énumérant les *namespaces*.
Pour tout connaître en détails, [la série d'articles de Michael Kerrisk sur les Pour tout connaître en détails, [la série d'articles de Michael Kerrisk sur les
*namespaces*](https://lwn.net/Articles/531114/) est excellente ! Auquel il faut *namespaces*](https://lwn.net/Articles/531114/) est excellente ! Auquel il faut
ajouter [l'article sur le plus récent `cgroup` ajouter [l'article sur le plus récent `cgroup`
*namespace*](https://lwn.net/Articles/621006/) et [le petit dernier sur le *namespace*](https://lwn.net/Articles/621006/) et [le petit dernier sur le
*namespace* `time`](https://lwn.net/Articles/766089/). *namespace* `time`](https://lwn.net/Articles/766089/).

View file

@ -6,11 +6,11 @@ Le *namespace* `network` {#net-ns}
### Introduction ### Introduction
L'espace de noms `network`, comme son nom l'indique permet de virtualiser tout L'espace de noms `network`, comme son nom l'indique permet de virtualiser tout
ce qui est en lien avec le réseau : les interfaces, les ports, les routes, les ce qui est en lien avec le réseau : les interfaces, les ports, les routes, les
règles de filtrage, etc. règles de filtrage, etc.
En entrant dans un nouvel espace de noms `network`, on se retrouve dans un En entrant dans un nouvel espace de noms `network`, on se retrouve dans un
environnement qui n'a plus qu'une interface de *loopback* : environnement qui n'a plus qu'une interface de *loopback* :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -25,7 +25,7 @@ environnement principal, il s'agit bien de deux interfaces isolées l'une de
l'autre. l'autre.
Qui dit nouvelle pile réseau, dit également que les ports qui sont assignés Qui dit nouvelle pile réseau, dit également que les ports qui sont assignés
dans l'espace principal, ne le sont plus dans le conteneur : il est donc dans l'espace principal, ne le sont plus dans le conteneur : il est donc
possible de lancer un serveur web sans qu'il n'entre en conflit avec celui d'un possible de lancer un serveur web sans qu'il n'entre en conflit avec celui d'un
autre espace de noms. autre espace de noms.
@ -33,9 +33,9 @@ autre espace de noms.
### Premiers pas avec `ip netns` ### Premiers pas avec `ip netns`
La suite d'outils `iproute2` propose une interface simplifiée pour utiliser le La suite d'outils `iproute2` propose une interface simplifiée pour utiliser le
*namespace* `network` : `ip netns`. *namespace* `network` : `ip netns`.
Nous pouvons tout d'abord créer un nouvel espace de noms : Nous pouvons tout d'abord créer un nouvel espace de noms :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -45,17 +45,17 @@ Nous pouvons tout d'abord créer un nouvel espace de noms :
La technique utilisée ici pour avoir des *namespaces* nommés est la même que La technique utilisée ici pour avoir des *namespaces* nommés est la même que
celle que nous avons vue dans celle que nous avons vue dans
[la première partie sur les *namespaces*](#ns-lifetime) : via un `mount --bind` [la première partie sur les *namespaces*](#ns-lifetime) : via un `mount --bind`
dans le dossier `/var/run/netns/`. Cela permet de faire persister le namespace dans le dossier `/var/run/netns/`. Cela permet de faire persister le namespace
malgré le fait que plus aucun processus ne s'y exécute. malgré le fait que plus aucun processus ne s'y exécute.
Maintenant que notre *namespace* est créé, nous pouvons regarder s'il contient Maintenant que notre *namespace* est créé, nous pouvons regarder s'il contient
des interfaces : des interfaces :
<div lang="en-US"> <div lang="en-US">
``` ```
42sh# ip netns exec virli ip link 42sh# ip netns exec virli ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1 1: lo: <LOOPBACK> mut 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
``` ```
</div> </div>
@ -64,7 +64,7 @@ Cette commande ne nous montre que l'interface de *loopback*, car nous n'avons
pour l'instant pas encore attaché la moindre interface. pour l'instant pas encore attaché la moindre interface.
D'ailleurs, cette interface est rapportée comme étant désactivée, activons-là D'ailleurs, cette interface est rapportée comme étant désactivée, activons-là
via la commande : via la commande :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -92,7 +92,7 @@ interface physique par conteneur, d'autant plus si l'on a plusieurs
centaines de conteneurs à gérer. centaines de conteneurs à gérer.
Une technique couramment employée consiste à créer une interface virtuelle de Une technique couramment employée consiste à créer une interface virtuelle de
type `veth` : type `veth` :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -100,16 +100,16 @@ type `veth` :
``` ```
</div> </div>
Une interface `veth` se comporte comme un tube bidirectionnel : tout ce qui Une interface `veth` se comporte comme un tube bidirectionnel : tout ce qui
entre d'un côté sort de l'autre et inversement. La commande précédente a donc entre d'un côté sort de l'autre et inversement. La commande précédente a donc
créé deux interfaces `veth0` et `veth1` : les paquets envoyés sur `veth0` sont créé deux interfaces `veth0` et `veth1` : les paquets envoyés sur `veth0` sont
donc reçus par `veth1` et les paquets envoyés à `veth1` sont reçus par `veth0`. donc reçus par `veth1` et les paquets envoyés à `veth1` sont reçus par `veth0`.
Dans cette configuration, ces deux interfaces ne sont pas très utiles, mais si Dans cette configuration, ces deux interfaces ne sont pas très utiles, mais si
l'on place l'une des deux extrémités dans un autre *namespace* `network`, il l'on place l'une des deux extrémités dans un autre *namespace* `network`, il
devient alors possible de réaliser un échange de paquets entre les deux. devient alors possible de réaliser un échange de paquets entre les deux.
Pour déplacer `veth1` dans notre *namespace* `virli` : Pour déplacer `veth1` dans notre *namespace* `virli` :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -117,7 +117,7 @@ Pour déplacer `veth1` dans notre *namespace* `virli` :
``` ```
</div> </div>
Il ne reste maintenant plus qu'à assigner une IP à chacune des interfaces : Il ne reste maintenant plus qu'à assigner une IP à chacune des interfaces :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -126,7 +126,7 @@ Il ne reste maintenant plus qu'à assigner une IP à chacune des interfaces :
``` ```
</div> </div>
Dès lors[^linkdown], nous pouvons `ping`er chaque extrêmité : Dès lors[^linkdown], nous pouvons `ping`er chaque extrêmité :
[^linkdown]: Il peut être nécessaire d'activer chaque lien, via `ip link set [^linkdown]: Il peut être nécessaire d'activer chaque lien, via `ip link set
vethX up`. vethX up`.
@ -140,7 +140,7 @@ Dès lors[^linkdown], nous pouvons `ping`er chaque extrêmité :
</div> </div>
Il ne reste donc pas grand chose à faire pour fournir Internet à notre Il ne reste donc pas grand chose à faire pour fournir Internet à notre
conteneur : via un peu de NAT ou grâce à un pont Ethernet. conteneur : via un peu de NAT ou grâce à un pont Ethernet.
### Les autres types d'interfaces ### Les autres types d'interfaces
@ -171,9 +171,9 @@ derrière notre machine.
<!-- https://hicu.be/bridge-vs-macvlan --> <!-- https://hicu.be/bridge-vs-macvlan -->
Lorsque l'on n'a pas assez de carte ethernet et que le switch ne supporte pas Lorsque l'on n'a pas assez de carte ethernet et que le switch ne supporte pas
les VLAN, le noyau met à disposition un routage basé sur les adresses MAC : le les VLAN, le noyau met à disposition un routage basé sur les adresses MAC : le
MACVLAN. S'il est activé dans votre noyau, vous allez avoir le choix entre l'un MACVLAN. S'il est activé dans votre noyau, vous allez avoir le choix entre l'un
des quatre modes : *private*, VEPA, *bridge* ou *passthru*. des quatre modes : *private*, VEPA, *bridge* ou *passthru*.
Quel que soit le mode choisi, les paquets en provenance d'autres machines et à Quel que soit le mode choisi, les paquets en provenance d'autres machines et à
destination d'un MAC seront délivrés à l'interface possédant la MAC. Les destination d'un MAC seront délivrés à l'interface possédant la MAC. Les
@ -189,7 +189,7 @@ la machine, c'est à l'équipement réseau derrière la machine de rerouter le
paquet vers la machine émettrice (par exemple un switch paquet vers la machine émettrice (par exemple un switch
[802.1Qbg](http://www.ieee802.org/1/pages/802.1bg.html)). [802.1Qbg](http://www.ieee802.org/1/pages/802.1bg.html)).
Pour construire une nouvelle interface de ce type : Pour construire une nouvelle interface de ce type :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -217,11 +217,11 @@ conteneur de la même machine.
##### *Bridge* ##### *Bridge*
À l'inverse des modes *VEPA* et *private*, les paquets sont routés selon leur À l'inverse des modes *VEPA* et *private*, les paquets sont routés selon leur
adresse MAC : si jamais une adresse MAC est connue, le paquet est délivré à adresse MAC : si jamais une adresse MAC est connue, le paquet est délivré à
l'interface MACVLAN correspondante ; dans le cas contraire, le paquet est l'interface MACVLAN correspondante ; dans le cas contraire, le paquet est
envoyé sur l'interface de sortie. envoyé sur l'interface de sortie.
Pour construire une nouvelle interface de ce type : Pour construire une nouvelle interface de ce type :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -233,9 +233,9 @@ Pour construire une nouvelle interface de ce type :
### Aller plus loin {-} ### Aller plus loin {-}
Pour approfondir les différentes techniques de routage, je vous Pour approfondir les différentes techniques de routage, je vous
recommande cet article : recommande cet article :
[Linux Containers and Networking](https://blog.flameeyes.eu/2010/09/linux-containers-and-networking). [Linux Containers and Networking](https://blog.flameeyes.eu/2010/09/linux-containers-and-networking).
Appliqué à Docker, vous apprécierez cet article : [Understanding Docker Appliqué à Docker, vous apprécierez cet article : [Understanding Docker
Networking Drivers and their use Networking Drivers and their use
cases](https://www.docker.com/blog/understanding-docker-networking-drivers-use-cases/). cases](https://www.docker.com/blog/understanding-docker-networking-drivers-use-cases/).

View file

@ -18,9 +18,9 @@ pas de PID en cours de route, puisqu'il dépend du *namespace* dans lequel il se
trouve. trouve.
### Isolons ! ### Isolons !
Première étape s'isoler : Première étape s'isoler :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -45,9 +45,9 @@ notre système initial. Pour s'en sortir, il est nécessaire de s'isoler dans un
*namespace* `mount` séparé. *namespace* `mount` séparé.
#### Double isolation : ajout du *namespace* `mount`\ #### Double isolation : ajout du *namespace* `mount`\
Voici la nouvelle ligne de commande que l'on va utiliser : Voici la nouvelle ligne de commande que l'on va utiliser :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -65,11 +65,11 @@ Cette fois, `top` et `ps` nous rapportent bien que l'on est seul dans notre
### Arborescence à l'extérieur du *namespace* ### Arborescence à l'extérieur du *namespace*
Lors de notre première tentative de `top`, lorsque `/proc` était encore monté Lors de notre première tentative de `top`, lorsque `/proc` était encore monté
sur le `procfs` de l'espace de noms initial : notre processus (au PID 1 dans sur le `procfs` de l'espace de noms initial : notre processus (au PID 1 dans
son nouveau *namespace*) était présent dans l'arborescence de l'espace initial son nouveau *namespace*) était présent dans l'arborescence de l'espace initial
avec un PID dans la continuité des autres processus, étonnant ! avec un PID dans la continuité des autres processus, étonnant !
En fait, l'isolation consiste en une virtualisation des numéros du processus : En fait, l'isolation consiste en une virtualisation des numéros du processus :
la plupart des processus du système initial ne sont pas accessibles, et ceux qui la plupart des processus du système initial ne sont pas accessibles, et ceux qui
font partie de l'espace de noms créé disposent d'une nouvelle numérotation. Et font partie de l'espace de noms créé disposent d'une nouvelle numérotation. Et
c'est cette nouvelle numérotation qui est montrée au processus. c'est cette nouvelle numérotation qui est montrée au processus.
@ -85,12 +85,12 @@ Au sein d'un *namespace*, le processus au PID 1 est considéré comme le
programme `init`, les mêmes propriétés s'appliquent donc. programme `init`, les mêmes propriétés s'appliquent donc.
Si un processus est orphelin, il est donc affiché comme étant fils du PID 1 Si un processus est orphelin, il est donc affiché comme étant fils du PID 1
dans son *namespace*[^PR_SET_CHILD_SUBREAPER] ; il n'est pas sorti de l'espace dans son *namespace*[^PR_SET_CHILD_SUBREAPER] ; il n'est pas sorti de l'espace
de noms. de noms.
[^PR_SET_CHILD_SUBREAPER]: en réalité, ce comportement est lié à la propriété [^PR_SET_CHILD_SUBREAPER]: en réalité, ce comportement est lié à la propriété
`PR_SET_CHILD_SUBREAPER`, qui peut être définie pour n'importe quel processus `PR_SET_CHILD_SUBREAPER`, qui peut être définie pour n'importe quel processus
de l'arborescence. Le processus au PID 1 hérite forcément de cette propriété\ ; de l'arborescence. Le processus au PID 1 hérite forcément de cette propriété\ ;
il va donc récupérer tous les orphelins, si aucun de leurs parents n'ont la il va donc récupérer tous les orphelins, si aucun de leurs parents n'ont la
propriété définie. propriété définie.
@ -104,4 +104,4 @@ l'intérieur pour conserver un comportement cohérent.
### Aller plus loin {-} ### Aller plus loin {-}
N'hésitez pas à jeter un œil à la page de manuel consacrée à cet espace de N'hésitez pas à jeter un œil à la page de manuel consacrée à cet espace de
noms : `pid_namespaces(7)`. noms : `pid_namespaces(7)`.

View file

@ -9,7 +9,7 @@ Projet et rendu
notation de ce cours.** notation de ce cours.**
Vous allez continuer aujourd'hui le projet qui s'étendra depuis le TP précédent Vous allez continuer aujourd'hui le projet qui s'étendra depuis le TP précédent
et qui consistera à réaliser la partie d'isolation de la moulinette des ACUs ! et qui consistera à réaliser la partie d'isolation de la moulinette des ACUs !
Cette semaine, il faudra faire en sorte de restreindre un groupe de processus Cette semaine, il faudra faire en sorte de restreindre un groupe de processus
pour qu'il s'exécute indépendemment de votre système. pour qu'il s'exécute indépendemment de votre système.
@ -17,8 +17,8 @@ pour qu'il s'exécute indépendemment de votre système.
Il n'y a pas de restriction sur le langage utilisé, vous pouvez tout aussi bien Il n'y a pas de restriction sur le langage utilisé, vous pouvez tout aussi bien
utiliser du C, du C++, du Python, du shell, etc. utiliser du C, du C++, du Python, du shell, etc.
L'usage de bibliothèques **non relatives** au projet est autorisé : le but de L'usage de bibliothèques **non relatives** au projet est autorisé : le but de
ce sujet est d'évaluer votre compréhension et votre utilisation de la ce sujet est d'évaluer votre compréhension et votre utilisation de la
tuyauterie bas-niveau du noyau liée à la virtualisation légère. À partir du tuyauterie bas-niveau du noyau liée à la virtualisation légère. À partir du
moment où vous n'utilisez pas une bibliothèque qui abstrait complètement cette moment où vous n'utilisez pas une bibliothèque qui abstrait complètement cette
plomberie, n'hésitez pas à l'utiliser ! plomberie, n'hésitez pas à l'utiliser !

View file

@ -3,9 +3,9 @@
Projet et rendu Projet et rendu
=============== ===============
Est attendu d'ici le TP suivant : Est attendu d'ici le TP suivant :
- le rendu des exercice de ce TP ; - le rendu des exercice de ce TP ;
- vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/15). - vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/15).
Pour les GISTRE (et en bonus pour les SRS), [un Pour les GISTRE (et en bonus pour les SRS), [un
@ -40,7 +40,7 @@ RAR, ...).
Voici une arborescence type (adaptez les extensions et les éventuels Voici une arborescence type (adaptez les extensions et les éventuels
fichiers supplémentaires associés au langage que vous aurez choisi fichiers supplémentaires associés au langage que vous aurez choisi
pour chaque exercice) : pour chaque exercice) :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -1,6 +1,6 @@
#### Exemple C\ #### Exemple C\
Voici un exemple de code C utilisant `setns(2)` : Voici un exemple de code C utilisant `setns(2)` :
<div lang="en-US"> <div lang="en-US">
```c ```c
@ -38,7 +38,7 @@ main(int argc, char *argv[])
#### Exemple shell\ #### Exemple shell\
Dans un shell, on utilisera la commande `nsenter(1)` : Dans un shell, on utilisera la commande `nsenter(1)` :
<div lang="en-US"> <div lang="en-US">
```bash ```bash

View file

@ -23,7 +23,7 @@ l'autre, d'une version du noyau à l'autre, il est normal d'avoir une liste de
aurons les mêmes. aurons les mêmes.
Ces fichiers sont en fait des liens symboliques un peu particuliers, car ils ne Ces fichiers sont en fait des liens symboliques un peu particuliers, car ils ne
pointent pas vers une destination valide : pointent pas vers une destination valide :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -52,7 +52,7 @@ On ne peut pas afficher tel quel les structures, mais on peut l'ouvrir avec
`setns(2)`. `setns(2)`.
Pour les commandes *shell*, il convient de donner en argument le chemin vers le Pour les commandes *shell*, il convient de donner en argument le chemin vers le
lien symbolique : la commande se chargera d'`open(2)` le fichier. lien symbolique : la commande se chargera d'`open(2)` le fichier.
#### `*_for_children`\ #### `*_for_children`\

View file

@ -5,7 +5,7 @@
Pour pouvoir suivre les exercices ci-après, vous devez disposez d'un noyau Pour pouvoir suivre les exercices ci-après, vous devez disposez d'un noyau
Linux, idéalement dans sa version 5.6 ou mieux. Il doit de plus être compilé Linux, idéalement dans sa version 5.6 ou mieux. Il doit de plus être compilé
avec les options suivantes (lorsqu'elles sont disponibles pour votre version) : avec les options suivantes (lorsqu'elles sont disponibles pour votre version) :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -28,7 +28,7 @@ Device Drivers --->
``` ```
</div> </div>
Les variables de configuration correspondantes sont : Les variables de configuration correspondantes sont :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -62,13 +62,13 @@ Nous allons utiliser des programmes issus des
[`procps-ng`](https://gitlab.com/procps-ng/procps) ainsi que ceux de la [`procps-ng`](https://gitlab.com/procps-ng/procps) ainsi que ceux de la
[`libcap`](https://sites.google.com/site/fullycapable/). [`libcap`](https://sites.google.com/site/fullycapable/).
Sous Debian et ses dérivés, ces paquets sont respectivement : Sous Debian et ses dérivés, ces paquets sont respectivement :
* `util-linux` * `util-linux`
* `procps` * `procps`
* `libcap2-bin` * `libcap2-bin`
Sous ArchLinux et ses dérivés, ces paquets sont respectivement : Sous ArchLinux et ses dérivés, ces paquets sont respectivement :
* `util-linux` * `util-linux`
* `procps-ng` * `procps-ng`
@ -79,17 +79,17 @@ Sous ArchLinux et ses dérivés, ces paquets sont respectivement :
La sécurité du *namespace* `user` a souvent été remise en cause par le passé, La sécurité du *namespace* `user` a souvent été remise en cause par le passé,
on lui attribue de nombreuses vulnérabilités. Vous devriez notamment consulter on lui attribue de nombreuses vulnérabilités. Vous devriez notamment consulter
à ce sujet : à ce sujet :
* [Security Implications of User Namespaces](https://blog.araj.me/security-implications-of-user-namespaces/) ; * [Security Implications of User Namespaces](https://blog.araj.me/security-implications-of-user-namespaces/) ;
* [Anatomy of a user namespaces vulnerability](https://lwn.net/Articles/543273/) ; * [Anatomy of a user namespaces vulnerability](https://lwn.net/Articles/543273/) ;
* <http://marc.info/?l=linux-kernel&m=135543612731939&w=2> ; * <http://marc.info/?l=linux-kernel&m=135543612731939&w=2> ;
* <http://marc.info/?l=linux-kernel&m=135545831607095&w=2>. * <http://marc.info/?l=linux-kernel&m=135545831607095&w=2>.
De nombreux projets ont choisi de ne pas autoriser l'utilisation de cet espace De nombreux projets ont choisi de ne pas autoriser l'utilisation de cet espace
de noms sans disposer de certaines *capabilities*[^userns-caps]. de noms sans disposer de certaines *capabilities*[^userns-caps].
[^userns-caps]: Sont nécessaires, conjointement : `CAP_SYS_ADMIN`, `CAP_SETUID` et `CAP_SETGID`. [^userns-caps]: Sont nécessaires, conjointement : `CAP_SYS_ADMIN`, `CAP_SETUID` et `CAP_SETGID`.
De nombreuses distributions ont choisi d'utiliser un paramètre du noyau pour De nombreuses distributions ont choisi d'utiliser un paramètre du noyau pour
adapter le comportement. adapter le comportement.
@ -99,7 +99,7 @@ adapter le comportement.
##### Debian et ses dérivées {.unnumbered} ##### Debian et ses dérivées {.unnumbered}
Si vous utilisez Debian ou l'un de ses dérivés, vous devrez autoriser Si vous utilisez Debian ou l'un de ses dérivés, vous devrez autoriser
explicitement cette utilisation non-privilégiée : explicitement cette utilisation non-privilégiée :
<div lang="en-US"> <div lang="en-US">
```bash ```bash

View file

@ -23,7 +23,7 @@ utilisateur, on obtient les privilèges requis pour créer tous les autres types
de *namespaces*. de *namespaces*.
Grâce à cette technique, il est possible de lancer des conteneurs en tant que Grâce à cette technique, il est possible de lancer des conteneurs en tant que
simple utilisateur ; le projet [Singularity](https://sylabs.io/) repose simple utilisateur ; le projet [Singularity](https://sylabs.io/) repose
en grande partie sur cela. en grande partie sur cela.
@ -34,11 +34,11 @@ garder dans le nouvel espace, que les utilisateurs et les groupes utiles au
processus, en les renumérotant au passage si besoin. processus, en les renumérotant au passage si besoin.
#### L'utilisateur -2 : *nobody*\ #### L'utilisateur -2 : *nobody*\
Lorsque l'on arrive dans un nouvel espace, aucun utilisateur ni groupe n'est Lorsque l'on arrive dans un nouvel espace, aucun utilisateur ni groupe n'est
défini. Dans cette situation, tous les identifiants d'utilisateur et de groupe, défini. Dans cette situation, tous les identifiants d'utilisateur et de groupe,
renvoyés par le noyau sont à -2 ; valeur qui correspond par convention à renvoyés par le noyau sont à -2 ; valeur qui correspond par convention à
l'utilisateur *nobody* et au groupe *nogroup*. l'utilisateur *nobody* et au groupe *nogroup*.
-1 étant réservé pour indiquer une erreur dans le retour d'une commande, ou la -1 étant réservé pour indiquer une erreur dans le retour d'une commande, ou la
@ -53,7 +53,7 @@ Pour établir la correspondance, une fois que l'on a créé le nouveau
##### `uid_map`\ ##### `uid_map`\
Sur chaque ligne, on doit indiquer : Sur chaque ligne, on doit indiquer :
- L'identifiant marquant le début de la plage d'utilisateurs, pour le processus - L'identifiant marquant le début de la plage d'utilisateurs, pour le processus
en question. en question.
@ -62,7 +62,7 @@ Sur chaque ligne, on doit indiquer :
- La taille de la plage. - La taille de la plage.
Par exemple, le *namespace* `user` initial défini la correspondance suivante : Par exemple, le *namespace* `user` initial défini la correspondance suivante :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -75,7 +75,7 @@ Cela signifie que les utilisateurs dont l'identifiant court de 0 à `MAX_INT -
2` inclus, dans cet espace de noms, correspondent aux utilisateurs allant de 0 à 2` inclus, dans cet espace de noms, correspondent aux utilisateurs allant de 0 à
`MAX_INT - 1` inclus, pour le processus affichant ce fichier. `MAX_INT - 1` inclus, pour le processus affichant ce fichier.
Lorsque l'on crée un *namespace* `user`, généralement, la correspondance vaut : Lorsque l'on crée un *namespace* `user`, généralement, la correspondance vaut :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -99,18 +99,18 @@ des groupes au lieu des utilisateurs.
<div lang="en-US"> <div lang="en-US">
```bash ```bash
42sh$ unshare --mount --pid --mount-proc --fork --net --user --map-root-user /bin/bash 42sh$ unshare --mount --pid --mount-proc --fork --net --user --map-root-user bash
``` ```
</div> </div>
Un `capsh --print` nous montre que l'on est bien `root` et que l'on possède Un `capsh --print` nous montre que l'on est bien `root` et que l'on possède
toutes les *capabilities*. Cependant, cela ne signifie pas que l'on a tous les toutes les *capabilities*. Cependant, cela ne signifie pas que l'on a tous les
droits sur le système ; il y a plusieurs niveaux de validation qui entrent en droits sur le système ; il y a plusieurs niveaux de validation qui entrent en
jeu. L'idée étant que l'on a été désigné root dans son conteneur, on devrait jeu. L'idée étant que l'on a été désigné root dans son conteneur, on devrait
pouvoir y faire ce que l'on veut, tant que l'on n'agit pas en dehors. pouvoir y faire ce que l'on veut, tant que l'on n'agit pas en dehors.
### Aller plus loin {-} ### Aller plus loin {-}
N'hésitez pas à jeter un œil à la page du manuel consacrée à ce *namespace* : N'hésitez pas à jeter un œil à la page du manuel consacrée à ce *namespace* :
`user_namespaces(7)`. `user_namespaces(7)`.

View file

@ -2,7 +2,9 @@ include ../pandoc-opts.mk
SOURCES_SRS = tutorial-srs.md \ SOURCES_SRS = tutorial-srs.md \
../devops/devops.md \ ../devops/devops.md \
../devops/what.md \ ../devops/what-srs.md \
../devops/what-ansible.md \
../devops/what-hosts.md \
../devops/tools.md \ ../devops/tools.md \
../devops/tools-gitea.md \ ../devops/tools-gitea.md \
../devops/tools-gitea-ansible.md \ ../devops/tools-gitea-ansible.md \
@ -12,6 +14,7 @@ SOURCES_SRS = tutorial-srs.md \
../devops/tools-drone-oauth.md \ ../devops/tools-drone-oauth.md \
../devops/tools-drone-runner.md \ ../devops/tools-drone-runner.md \
../devops/tools-drone-runner-ansible.md \ ../devops/tools-drone-runner-ansible.md \
../devops/tools-drone-runner-end.md \
../devops/tools-end.md \ ../devops/tools-end.md \
../devops/ci.md \ ../devops/ci.md \
../devops/publish-docker.md \ ../devops/publish-docker.md \
@ -19,6 +22,8 @@ SOURCES_SRS = tutorial-srs.md \
SOURCES_GISTRE = tutorial-gistre.md \ SOURCES_GISTRE = tutorial-gistre.md \
../devops/what-gistre.md \ ../devops/what-gistre.md \
../devops/what-cmd.md \
../devops/what-hosts.md \
../devops/what-gistre-see-srs.md \ ../devops/what-gistre-see-srs.md \
../devops/tools.md \ ../devops/tools.md \
../devops/tools-gitea.md \ ../devops/tools-gitea.md \
@ -29,6 +34,7 @@ SOURCES_GISTRE = tutorial-gistre.md \
../devops/tools-drone-oauth.md \ ../devops/tools-drone-oauth.md \
../devops/tools-drone-runner.md \ ../devops/tools-drone-runner.md \
../devops/tools-drone-runner-cmd.md \ ../devops/tools-drone-runner-cmd.md \
../devops/tools-drone-runner-end.md \
../devops/tools-end.md \ ../devops/tools-end.md \
../devops/ci-gistre.md \ ../devops/ci-gistre.md \
../devops/run-gistre.md \ ../devops/run-gistre.md \

View file

@ -34,7 +34,7 @@ Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...). placer dans une tarball (pas d'archive ZIP, RAR, ...).
Voici une arborescence type (vous pourriez avoir des fichiers Voici une arborescence type (vous pourriez avoir des fichiers
supplémentaires) : supplémentaires) :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -34,7 +34,7 @@ Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...). placer dans une tarball (pas d'archive ZIP, RAR, ...).
Voici une arborescence type (vous pourriez avoir des fichiers Voici une arborescence type (vous pourriez avoir des fichiers
supplémentaires) : supplémentaires) :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -29,7 +29,7 @@ Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...). placer dans une tarball (pas d'archive ZIP, RAR, ...).
Voici une arborescence type (vous pourriez avoir des fichiers Voici une arborescence type (vous pourriez avoir des fichiers
supplémentaires) : supplémentaires) :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -1,13 +1,13 @@
--- ---
title: Virtualisation légère -- TP n^o^ 5 title: Virtualisation légère -- TP n^o^ 5
subtitle: "Application des conteneurs : tests et intégration continue" subtitle: "Application des conteneurs : tests et intégration continue"
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps} author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA institute: EPITA
date: Jeudi 4 novembre 2021 date: Jeudi 4 novembre 2021
abstract: | abstract: |
Durant ce nouveau TP, appréhenderons l'intégration continue et nous Durant ce nouveau TP, appréhenderons l'intégration continue et nous
plongerons dans l'IoT pour trouver une solution innovante à des problèmes de plongerons dans l'IoT pour trouver une solution innovante à des problèmes de
déploiement ! déploiement !
\vspace{1em} \vspace{1em}

View file

@ -6,7 +6,7 @@ institute: EPITA
date: Jeudi 4 novembre 2021 date: Jeudi 4 novembre 2021
abstract: | abstract: |
Durant ce nouveau TP, nous allons jouer les DevOps et déployer Durant ce nouveau TP, nous allons jouer les DevOps et déployer
automatiquement des services ! automatiquement des services !
\vspace{1em} \vspace{1em}

View file

@ -6,7 +6,7 @@ institute: EPITA
date: Jeudi 4 novembre 2021 date: Jeudi 4 novembre 2021
abstract: | abstract: |
Durant ce nouveau TP, nous allons jouer les DevOps et déployer Durant ce nouveau TP, nous allons jouer les DevOps et déployer
automatiquement des services ! automatiquement des services !
\vspace{1em} \vspace{1em}

View file

@ -4,7 +4,7 @@ function Div(el)
-- insert element in front -- insert element in front
table.insert( table.insert(
el.content, 1, el.content, 1,
pandoc.RawBlock("latex", "\\begin{alertbox}")) pandoc.RawBlock("latex", "\\noindent\\begin{alertbox}"))
-- insert element at the back -- insert element at the back
table.insert( table.insert(
el.content, el.content,
@ -15,7 +15,7 @@ function Div(el)
-- insert element in front -- insert element in front
table.insert( table.insert(
el.content, 1, el.content, 1,
pandoc.RawBlock("latex", "\\begin{codebox}")) pandoc.RawBlock("latex", "\\noindent\\begin{codebox}"))
-- insert element at the back -- insert element at the back
table.insert( table.insert(
el.content, el.content,
@ -26,7 +26,7 @@ function Div(el)
-- insert element in front -- insert element in front
table.insert( table.insert(
el.content, 1, el.content, 1,
pandoc.RawBlock("latex", "\\begin{questionbox}")) pandoc.RawBlock("latex", "\\noindent\\begin{questionbox}"))
-- insert element at the back -- insert element at the back
table.insert( table.insert(
el.content, el.content,

View file

@ -3,4 +3,4 @@
Déploiement Déploiement
=========== ===========
TODO il faudrait pouvoir cliquer sur le bouton pour mettre à jour l'image docker qui tourne localement ? en passant par Ansible ? TODO il faudrait pouvoir cliquer sur le bouton pour mettre à jour l'image docker qui tourne localement ? en passant par Ansible ?

View file

@ -21,11 +21,11 @@ configuration des dépôts.
::::: :::::
Une fois Gitea et Drone installés et configurés, nous allons pouvoir rentrer Une fois Gitea et Drone installés et configurés, nous allons pouvoir rentrer
dans le vif du sujet : faire de l'intégration continue sur notre premier projet ! dans le vif du sujet : faire de l'intégration continue sur notre premier projet !
### Créez un dépôt pour `linky2influx` ### Créez un dépôt pour `linky2influx`
Après avoir créé (ou migré pour les plus malins !) le dépôt Après avoir créé (ou migré pour les plus malins !) le dépôt
[`linky2influx`](https://git.nemunai.re/nemunaire/linky2influx) dans Drone, [`linky2influx`](https://git.nemunai.re/nemunaire/linky2influx) dans Drone,
synchronisez les dépôts, puis activez la surveillance de `linky2influx`. synchronisez les dépôts, puis activez la surveillance de `linky2influx`.
@ -57,33 +57,33 @@ Committons puis poussons notre travail. Dès qu'il sera reçu par Gitea, nous
devrions voir l'interface de Drone lancer les étapes décrites dans le fichier. devrions voir l'interface de Drone lancer les étapes décrites dans le fichier.
::::: {.warning} ::::: {.warning}
**IMPORTANT :** si vous avez l'impression que ça ne marche pas et que vous avez **IMPORTANT :** si vous avez l'impression que ça ne marche pas et que vous avez
réutilisé le fichier présent sur le dépôt au lieu de partir de l'exemple donné réutilisé le fichier présent sur le dépôt au lieu de partir de l'exemple donné
dans la documentation, **commencez en partant de l'exemple de la dans la documentation, **commencez en partant de l'exemple de la
documentation** ! Le fichier présent sur le dépôt **ne fonctionnera pas** dans documentation** ! Le fichier présent sur le dépôt **ne fonctionnera pas** dans
votre situation ! votre situation !
::::: :::::
![Drone en action](../devops/drone-run-linky.png){height=7.5cm} ![Drone en action](../devops/drone-run-linky.png){height=7.5cm}
Lorsqu'apparaît enfin la ligne `git.nemunai.re/linky2influx`, le projet est compilé ! Lorsqu'apparaît enfin la ligne `git.nemunai.re/linky2influx`, le projet est compilé !
### Publier le binaire correspondant aux tags/jalons ### Publier le binaire correspondant aux tags/jalons
Nous savons maintenant que notre projet compile bien dans un environnement Nous savons maintenant que notre projet compile bien dans un environnement
différent de celui du développeur ! Néanmoins, le binaire produit est perdu dès différent de celui du développeur ! Néanmoins, le binaire produit est perdu dès
lors que la compilation est terminée, car nous n'en faisons rien. lors que la compilation est terminée, car nous n'en faisons rien.
Ajoutons donc une nouvelle règle à notre `.droneci.yml` pour placer le binaire Ajoutons donc une nouvelle règle à notre `.droneci.yml` pour placer le binaire
au sein de la liste des fichiers téléchargeable aux côtés des tags. au sein de la liste des fichiers téléchargeable aux côtés des tags.
Vous aurez sans doute besoin de : Vous aurez sans doute besoin de :
- <https://docs.drone.io/pipeline/conditions/> - <https://docs.drone.io/pipeline/conditions/>
- <http://plugins.drone.io/drone-plugins/drone-gitea-release/> - <http://plugins.drone.io/drone-plugins/drone-gitea-release/>
Attention à ne pas stocker votre clef d'API dans le fichier YAML ! Attention à ne pas stocker votre clef d'API dans le fichier YAML !
![Binaire publié automatiquement sur Gitea](../devops/tag-released.png){height=8cm} ![Binaire publié automatiquement sur Gitea](../devops/tag-released.png){height=8cm}
@ -95,16 +95,16 @@ l'interface de Drone.
::::: :::::
### Publier pour plusieurs architectures ? ### Publier pour plusieurs architectures ?
Le compilateur Go est fourni avec l'ensemble des backends des différentes Le compilateur Go est fourni avec l'ensemble des backends des différentes
architectures matérielles qu'il supporte, nous pouvons donc aisément faire de architectures matérielles qu'il supporte, nous pouvons donc aisément faire de
la compilation croisée pour d'autres architectures. la compilation croisée pour d'autres architectures.
Essayons maintenant de compiler `linky2influx` pour plusieurs architectures afin de Essayons maintenant de compiler `linky2influx` pour plusieurs architectures afin de
vérifier que cela fonctionne bien ! vérifier que cela fonctionne bien !
Un exemple est donné tout en haut de cette page : Un exemple est donné tout en haut de cette page :
<https://docs.drone.io/pipeline/environment/syntax/>. <https://docs.drone.io/pipeline/environment/syntax/>.
En faisant varier `$GOARCH` en `mips`, `powerpc`, ... nous pouvons générer les En faisant varier `$GOARCH` en `mips`, `powerpc`, ... nous pouvons générer les

View file

@ -3,24 +3,26 @@
## Intégration continue ## Intégration continue
Une fois Gitea et Drone installés et configurés, nous allons pouvoir rentrer Une fois Gitea et Drone installés et configurés, nous allons pouvoir rentrer
dans le vif du sujet : faire de l'intégration continue sur notre premier projet ! dans le vif du sujet : faire de l'intégration continue sur notre premier projet !
### Créez un dépôt pour `youp0m` ### Créez un dépôt pour `youp0m`
Reprenez les travaux réalisés au TP précédent. Nous allons notamment avoir Reprenez les travaux déjà réalisés : nous allons notamment avoir besoin du
besoin du `Dockerfile` dans la section suivante. `Dockerfile` que nous avons réalisé pour ce projet `youp0m`.
Après avoir créé (ou migré pour les plus malins !) le dépôt Après avoir créé (ou migré pour les plus malins !) le dépôt
[`youp0m`](https://git.nemunai.re/nemunaire/youp0m) dans Drone, `youp0m`[^urlyoup0m] dans gitea, synchronisez les dépôts dans Drone, puis
synchronisez les dépôts, puis activez la surveillance de `youp0m`. activez la surveillance de `youp0m`.
Nous allons devoir rédiger un fichier `.drone.yml`, que l'on placera à la racine [^urlyoup0m]: <https://git.nemunai.re/nemunaire/youp0m>
Nous allons devoir rédiger un fichier `drone.yml`, que l'on placera à la racine
du dépôt. C'est ce fichier qui sera traité par DroneCI pour savoir comment du dépôt. C'est ce fichier qui sera traité par DroneCI pour savoir comment
compiler et tester le projet. compiler et tester le projet.
::::: {.warning} ::::: {.warning}
Un fichier `.drone.yml` existe déjà à la racine du dépôt. Celui-ci pourra vous Un fichier `drone.yml` existe déjà à la racine du dépôt. Celui-ci pourra vous
servir d'inspiration, mais il ne fonctionnera pas directement sur votre servir d'inspiration, mais il ne fonctionnera pas directement dans votre
installation. installation.
**Vous rencontrerez des problèmes inattendus si vous utilisez le fichier **Vous rencontrerez des problèmes inattendus si vous utilisez le fichier
@ -32,11 +34,11 @@ documentation pour obtenir un `.drone.yml` fonctionnel.
### Définir les étapes d'intégration ### Définir les étapes d'intégration
Toutes les informations nécessaires à l'écriture du fichier `.drone.yml` se Toutes les informations nécessaires à l'écriture du fichier `.drone.yml` se
trouvent dans [l'excellente documentation du trouvent dans l'excellente documentation du projet :\
projet](https://docs.drone.io/pipeline/docker/examples/languages/golang/). <https://docs.drone.io/pipeline/docker/examples/languages/golang/>.
Les étapes sont sensiblement les mêmes que dans le `Dockerfile` que nous avons Les étapes sont sensiblement les mêmes que dans le `Dockerfile` que nous avons
écrit lors du TP précédent. écrit précédemment.
Committons puis poussons notre travail. Dès qu'il sera reçu par Gitea, nous Committons puis poussons notre travail. Dès qu'il sera reçu par Gitea, nous
devrions voir l'interface de Drone lancer les étapes décrites dans le fichier. devrions voir l'interface de Drone lancer les étapes décrites dans le fichier.
@ -44,23 +46,22 @@ devrions voir l'interface de Drone lancer les étapes décrites dans le fichier.
![Drone en action](../devops/drone-run.png){height=6cm} ![Drone en action](../devops/drone-run.png){height=6cm}
::::: {.warning} ::::: {.warning}
**IMPORTANT :** si vous avez l'impression que ça ne marche pas et que vous avez **IMPORTANT :** si vous avez l'impression que ça ne marche pas et que vous avez
réutilisé le fichier présent sur le dépôt au lieu de partir de l'exemple donné réutilisé le fichier présent sur le dépôt au lieu de partir de l'exemple donné
dans la documentation, **commencez en partant de l'exemple de la dans la documentation, **commencez en partant de l'exemple de la
documentation** ! Le fichier présent sur le dépôt **ne fonctionnera pas** dans documentation** ! Le fichier présent sur le dépôt **ne fonctionnera pas** dans
votre situation ! votre situation !
::::: :::::
Lorsqu'apparaît enfin la ligne `git.nemunai.re/youp0m`, le projet est compilé ! Lorsqu'apparaît enfin la ligne `git.nemunai.re/youp0m`, le projet est compilé !
### Inspection qualité ### Inspection qualité
Nous n'avons pas encore de test à proprement parler. Nous allons utiliser Nous n'avons pas encore de test à proprement parler. Nous allons utiliser
[Sonarqube](https://www.sonarqube.org/) pour faire une revue qualité du code ! [Sonarqube](https://www.sonarqube.org/) pour faire une revue qualité du code !
Tout d'abord, il faut lancer le conteneur Sonarqube (SRS, pensez à l'ajouter à Tout d'abord, il faut lancer le conteneur Sonarqube :
votre playbook !) :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -72,7 +73,7 @@ Le service met un bon moment avant de démarrer, dès qu'il se sera initialisé,
nous pourrons accéder à l'interface sur <http://localhost:9000>. nous pourrons accéder à l'interface sur <http://localhost:9000>.
En attendant qu'il démarre, nous pouvons commencer à ajouter le nécessaire à En attendant qu'il démarre, nous pouvons commencer à ajouter le nécessaire à
notre `.drone.yml` : <http://plugins.drone.io/aosapps/drone-sonar-plugin/>. notre `.drone.yml` : <http://plugins.drone.io/aosapps/drone-sonar-plugin/>.
Après s'être connecté à Sonarqube (`admin:admin`), nous pouvons aller générer Après s'être connecté à Sonarqube (`admin:admin`), nous pouvons aller générer
un token, tel que décrit dans la [documentation du plugin un token, tel que décrit dans la [documentation du plugin
@ -86,18 +87,18 @@ qui en fera une analyse minutieuse. Rendez-vous sur
### Publier le binaire correspondant aux tags/jalons ### Publier le binaire correspondant aux tags/jalons
Nous savons maintenant que notre projet compile bien dans un environnement Nous savons maintenant que notre projet compile bien dans un environnement
différent de celui du développeur ! Néanmoins, le binaire produit est perdu dès différent de celui du développeur ! Néanmoins, le binaire produit est perdu dès
lors que la compilation est terminée, car nous n'en faisons rien. lors que la compilation est terminée, car nous n'en faisons rien.
Ajoutons donc une nouvelle règle à notre `.droneci.yml` pour placer le binaire Ajoutons donc une nouvelle règle à notre `.droneci.yml` pour placer le binaire
au sein de la liste des fichiers téléchargeables aux côtés des tags. au sein de la liste des fichiers téléchargeables aux côtés des tags.
Vous aurez sans doute besoin de : Vous aurez sans doute besoin de :
- <https://docs.drone.io/pipeline/conditions/> - <https://docs.drone.io/pipeline/conditions/>
- <http://plugins.drone.io/drone-plugins/drone-gitea-release/> - <http://plugins.drone.io/drone-plugins/drone-gitea-release/>
Attention à ne pas stocker votre clef d'API dans le fichier YAML ! Attention à ne pas stocker votre clef d'API dans le fichier YAML !
![Binaire publié automatiquement sur Gitea](../devops/tag-released.png){height=8cm} ![Binaire publié automatiquement sur Gitea](../devops/tag-released.png){height=8cm}

View file

@ -4,13 +4,13 @@ Le mouvement DevOps
=================== ===================
Jusqu'à récemment, et encore dans de nombreuses entreprises, les développeurs Jusqu'à récemment, et encore dans de nombreuses entreprises, les développeurs
et les administrateurs système faisaient partie de deux équipes différentes : et les administrateurs système faisaient partie de deux équipes différentes :
les uns développant sur leurs machines avec les dernières bibliothèques, les uns développant sur leurs machines avec les dernières bibliothèques,
utilisant les derniers frameworks à la mode, sans se préoccuper de la sécurité utilisant les derniers frameworks à la mode, sans se préoccuper de la sécurité
(ils travaillent en `root` ou avec `sudo` ;)), tandis que les autres tentaient (ils travaillent en `root` ou avec `sudo` ;)), tandis que les autres tentaient
tant bien que mal de déployer ces services avec les contraintes opérationnelles tant bien que mal de déployer ces services avec les contraintes opérationnelles
en tête.\ en tête.\
Ces contraintes : tant liées à la **sécurité** (il faut s'assurer Ces contraintes : tant liées à la **sécurité** (il faut s'assurer
qu'un service n'utilise pas une bibliothèque vulnérable par exemple, donc soit qu'un service n'utilise pas une bibliothèque vulnérable par exemple, donc soit
utilisé sur un système à jour, et qu'il ne tourne pas en `root`), qu'à la utilisé sur un système à jour, et qu'il ne tourne pas en `root`), qu'à la
**disponibilité** (si le service est mal codé est contient beaucoup de fuites **disponibilité** (si le service est mal codé est contient beaucoup de fuites
@ -19,13 +19,13 @@ pâtissent).
Une guerre faisait donc rage entre les développeurs qui ne comprenaient pas que Une guerre faisait donc rage entre les développeurs qui ne comprenaient pas que
les administrateurs système ne pouvaient pas maintenir autant de versions d'une les administrateurs système ne pouvaient pas maintenir autant de versions d'une
bibliothèque qu'il y avait de services : par exemple dans le cas de plusieurs bibliothèque qu'il y avait de services : par exemple dans le cas de plusieurs
services en PHP, on pouvait leur demander de déployer des applications services en PHP, on pouvait leur demander de déployer des applications
utilisant la version 5.6, et la 7.2 pour d'autres, ... lorsqu'il y avait des utilisant la version 5.6, et la 7.2 pour d'autres, ... lorsqu'il y avait des
incompatibilités mineures et plus personne pour s'occuper de la maintenance incompatibilités mineures et plus personne pour s'occuper de la maintenance
d'un vieux service toujours utilisé. d'un vieux service toujours utilisé.
Le même principe est aussi valable pour Python, Ruby, ... : les développeurs Le même principe est aussi valable pour Python, Ruby, ... : les développeurs
ont toujours eu tendance à vouloir utiliser les dernières améliorations d'un ont toujours eu tendance à vouloir utiliser les dernières améliorations d'un
langage, mais les administrateurs système n'ont alors pas de paquets stables langage, mais les administrateurs système n'ont alors pas de paquets stables
dans la distribution. En effet, les distributions stables telles que Debian, dans la distribution. En effet, les distributions stables telles que Debian,
@ -64,10 +64,10 @@ charges, les pannes, ...
::::: {.warning} ::::: {.warning}
Attention par contre aux entreprises qui recrutent un profil DevOps, car cela a Attention par contre aux entreprises qui recrutent un profil DevOps, car cela a
autant de sens que recruter un développeur Scrum ou un développeur cycle en V : autant de sens que recruter un développeur Scrum ou un développeur cycle en V :
DevOps est une méthodologie. Les entreprises qui recrutent un DevOps DevOps est une méthodologie. Les entreprises qui recrutent un DevOps
recherchent généralement quelqu'un qui fera à la fois du développement logiciel recherchent généralement quelqu'un qui fera à la fois du développement logiciel
d'un côté et de l'administration système de l'autre : une situation d'un côté et de l'administration système de l'autre : une situation
généralement assez difficile à vivre. Alors qu'au contraire, la mouvance DevOps généralement assez difficile à vivre. Alors qu'au contraire, la mouvance DevOps
doit être prise au sérieux par l'ensemble des développeurs. Lors d'un entretien doit être prise au sérieux par l'ensemble des développeurs. Lors d'un entretien
d'embauche pour ce genre de poste, assurez-vous bien de ne pas être le seul à d'embauche pour ce genre de poste, assurez-vous bien de ne pas être le seul à
@ -77,14 +77,14 @@ faire du DevOps.
## Intégration continue ## Intégration continue
L'**intégration continue** est la première brique à mettre en place : le but L'**intégration continue** est la première brique à mettre en place : le but
est de compiler automatiquement chaque commit dans un environnement proche de est de compiler automatiquement chaque commit dans un environnement proche de
celui de production, puis de lancer les suites de tests du logiciel. celui de production, puis de lancer les suites de tests du logiciel.
Cela permet de détecter les problèmes au plus tôt dans le cycle de Cela permet de détecter les problèmes au plus tôt dans le cycle de
développement, mais cela permet également d'améliorer la qualité du code sur le développement, mais cela permet également d'améliorer la qualité du code sur le
long terme, car on peut y ajouter facilement des outils qui vont se charger long terme, car on peut y ajouter facilement des outils qui vont se charger
automatiquement de réaliser des analyses : cela peut aller de la couverture des automatiquement de réaliser des analyses : cela peut aller de la couverture des
tests, à de l'analyse statique ou dynamique de binaire, en passant par la tests, à de l'analyse statique ou dynamique de binaire, en passant par la
recherche de vulnérabilités ou de mauvaises pratiques de programmation. recherche de vulnérabilités ou de mauvaises pratiques de programmation.
@ -101,7 +101,7 @@ les développeurs considéreront avoir atteint un jalon, une version stable.
## Déploiement continu ## Déploiement continu
Une fois tous les tests passés et les objets produits (on parle d'*artifact* ou Une fois tous les tests passés et les objets produits (on parle d'*artifact* ou
d'*assets*), il est possible de déclencher un déploiement : il s'agit de rendre d'*assets*), il est possible de déclencher un déploiement : il s'agit de rendre
accessible aux utilisateurs finaux le service ou les objets. accessible aux utilisateurs finaux le service ou les objets.
Dans le cas d'un programme à télécharger Dans le cas d'un programme à télécharger
@ -113,15 +113,15 @@ vers la dernière version (pour que les utilisateurs aient la notifications).
Ou bien dans le cas d'un service en ligne (GitHub, Netflix, GMail, ...), il Ou bien dans le cas d'un service en ligne (GitHub, Netflix, GMail, ...), il
s'agira de mettre à jour le service. s'agira de mettre à jour le service.
Parfois les deux seront à faire : à la fois publier un paquet ou un Parfois les deux seront à faire : à la fois publier un paquet ou un
conteneur et mettre à jour un service en ligne : par exemple, [le conteneur et mettre à jour un service en ligne : par exemple, [le
serveur Synapse](https://buildkite.com/matrix-dot-org/synapse) du serveur Synapse](https://buildkite.com/matrix-dot-org/synapse) du
protocole de messagerie Matrix ou encore protocole de messagerie Matrix ou encore
[Gitlab](https://gitlab.com/gitlab-org/gitlab/-/pipelines), tous deux [Gitlab](https://gitlab.com/gitlab-org/gitlab/-/pipelines), tous deux
publient des paquets à destination de leurs communautés, et mettent à publient des paquets à destination de leurs communautés, et mettent à
jour leur service en ligne.\ jour leur service en ligne.\
Il existe pour cela de très nombreuses stratégies : lorsque l'on n'a pas Il existe pour cela de très nombreuses stratégies : lorsque l'on n'a pas
beaucoup de trafic ni beaucoup de machines, on peut simplement éteindre beaucoup de trafic ni beaucoup de machines, on peut simplement éteindre
l'ancien service et démarrer le nouveau, si ça prend quelques millisecondes en l'ancien service et démarrer le nouveau, si ça prend quelques millisecondes en
étant automatisé, cela peut être suffisant compte tenu du faible étant automatisé, cela peut être suffisant compte tenu du faible
@ -133,11 +133,11 @@ de tout rallumer. Déjà parce que trop de visiteurs vont se retrouver avec des
pages d'erreur, et aussi parce qu'en cas de bug logiciel qui n'aurait pas été pages d'erreur, et aussi parce qu'en cas de bug logiciel qui n'aurait pas été
vu malgré les étapes précédentes, cela pourrait créer une situation vu malgré les étapes précédentes, cela pourrait créer une situation
catastrophique (imaginez qu'on ne puisse plus valider une commande sur Amazon à catastrophique (imaginez qu'on ne puisse plus valider une commande sur Amazon à
cause d'une ligne commentée par erreur !).\ cause d'une ligne commentée par erreur !).\
On va donc privilégier un déploiement progressif de la nouvelle version (que On va donc privilégier un déploiement progressif de la nouvelle version (que
l'on va étendre sur plusieurs minutes, heures ou mêmes jours), en éteignant l'on va étendre sur plusieurs minutes, heures ou mêmes jours), en éteignant
tour à tour les instances, et en veillant à ce que les métriques (voir la tour à tour les instances, et en veillant à ce que les métriques (voir la
section suivante !) soient constantes. section suivante !) soient constantes.
## Monitoring et supervision ## Monitoring et supervision
@ -145,16 +145,16 @@ section suivante !) soient constantes.
Une fois déployé, le service peut avoir des ratés, alors il convient de le Une fois déployé, le service peut avoir des ratés, alors il convient de le
surveiller afin d'être le plus proactif possible dans la résolution des surveiller afin d'être le plus proactif possible dans la résolution des
problèmes. La pire situation est celle dans laquelle c'est un utilisateur qui problèmes. La pire situation est celle dans laquelle c'est un utilisateur qui
nous informe d'un problème... (sur Twitter !?) nous informe d'un problème... (sur Twitter !?)
Nous avons réalisé précédemment une partie collecte de métriques, avec nos Nous avons réalisé précédemment une partie collecte de métriques, avec nos
conteneurs TICK. Nous n'allons donc pas nous en occuper aujourd'hui. conteneurs TICK. Nous n'allons donc pas nous en occuper aujourd'hui.
\ \
Notez tout de même qu'il y a deux grandes catégories de logiciels de Notez tout de même qu'il y a deux grandes catégories de logiciels de
supervision : supervision :
**Basée sur des états** comme Nagios, Zabbix, ... : ces logiciels vont **Basée sur des états** comme Nagios, Zabbix, ... : ces logiciels vont
simplement réaliser des séries de tests définis, à intervalles réguliers et simplement réaliser des séries de tests définis, à intervalles réguliers et
contacter l'administrateur d'astreinte dès qu'un test ne passe plus de manière contacter l'administrateur d'astreinte dès qu'un test ne passe plus de manière
persistante. persistante.
@ -163,8 +163,8 @@ Il y a rarement beaucoup d'intelligence ou d'anticipation automatique dans ces
outils. outils.
\ \
**Basée sur les métriques** comme ELK, Prometheus, InfluxDB, ... : dans la **Basée sur les métriques** comme ELK, Prometheus, InfluxDB, ... : dans la
stack TICK que nous avons mis en place au précédent TP, nous avions placé un stack TICK que nous avons mis en place précédemment, nous avions placé un
agent sur la machine que nous souhaitions analyser. Outre les graphiques agent sur la machine que nous souhaitions analyser. Outre les graphiques
présenté dans Chronograf, le dernier outil que l'on n'avait pas configuré était présenté dans Chronograf, le dernier outil que l'on n'avait pas configuré était
Kapacitor, qui permet après avoir analysé les données, d'alerter en fonction Kapacitor, qui permet après avoir analysé les données, d'alerter en fonction
@ -196,4 +196,4 @@ des pannes, des latences, ... à n'importe quel niveau du produit, afin d'en
tester (brulatement certes) sa résilience. Cela oblige les développeurs, les tester (brulatement certes) sa résilience. Cela oblige les développeurs, les
opérationnels et les architectes à concevoir des services hautement tolérant opérationnels et les architectes à concevoir des services hautement tolérant
aux pannes, ce qui fait que le jour où une véritable panne survient, elle n'a aux pannes, ce qui fait que le jour où une véritable panne survient, elle n'a
aucun impact sur la production (enfin on espère !). aucun impact sur la production (enfin on espère !).

View file

@ -7,13 +7,12 @@ Toutes les tâches de publication peuvent s'assimiler à des tâches de
déploiement continu. C'est en particulier le cas lorsque le produit de déploiement continu. C'est en particulier le cas lorsque le produit de
compilation sera simplement publié et qu'il n'y a pas de service à mettre à compilation sera simplement publié et qu'il n'y a pas de service à mettre à
jour ensuite (par exemple, dans le cas de Firefox ou de LibreOffice, une fois jour ensuite (par exemple, dans le cas de Firefox ou de LibreOffice, une fois
testés, les paquets sont envoyés sur le serveur d'où ils seront distribués ; il testés, les paquets sont envoyés sur le serveur d'où ils seront distribués ; il
n'y a pas de service/docker à relancer). n'y a pas de service/docker à relancer).
À l'inverse, `youp0m` ou `linky2influx` sont à la fois des programmes que l'on À l'inverse, `youp0m` est à la fois un programme que l'on peut télécharger et
peut télécharger et des services qu'il faut déployer pour les mettre à un service qu'il faut déployer pour le mettre à jour. Pour simplifier le
jour. Pour simplifier le déploiement, nous utilisons des images Docker. Il faut déploiement, nous utilisons une image Docker. Il faut cependant la générer ...
cependant les générer ...
## Mise en place du registre ## Mise en place du registre
@ -25,7 +24,7 @@ Docker intégré. Si vous utilisez Gitea, continuez cette section.
Afin de disposer de notre propre registre Docker sur lequel publier nos images, Afin de disposer de notre propre registre Docker sur lequel publier nos images,
nous allons utiliser l'image de registre fournie par Docker. Elle se lance nous allons utiliser l'image de registre fournie par Docker. Elle se lance
comme suit : comme suit :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -37,7 +36,7 @@ Vous trouverez davantage d'informations pour le déploiement
[ici](https://docs.docker.com/registry/deploying/). [ici](https://docs.docker.com/registry/deploying/).
Nous pouvons tester le bon fonctionnement de notre registre avec la commande Nous pouvons tester le bon fonctionnement de notre registre avec la commande
suivante : suivante :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -50,7 +49,7 @@ suivante :
## Publication de l'image ## Publication de l'image
Une fois le registre démarré, il ne nous reste plus qu'à ajouter une étape de Une fois le registre démarré, il ne nous reste plus qu'à ajouter une étape de
publication de l'image Docker. Cela se fait au moyen du plugin suivant : publication de l'image Docker. Cela se fait au moyen du plugin suivant :\
<http://plugins.drone.io/drone-plugins/drone-docker/>. <http://plugins.drone.io/drone-plugins/drone-docker/>.
Sans plus de configuration, le registre que nous avons démarré Sans plus de configuration, le registre que nous avons démarré
@ -62,7 +61,7 @@ pour utiliser `https`, il est nécessaire de définir l'option
## Test de l'image ## Test de l'image
Sur l'hôte, nous pouvons tester que l'image a bien été publiée grâce à la Sur l'hôte, nous pouvons tester que l'image a bien été publiée grâce à la
commande suivante : commande suivante :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -92,8 +91,8 @@ une machine virtuelle avec une connexion SSH. N'hésitez pas à l'ajouter à vot
`.droneci.yml`. `.droneci.yml`.
## Profitons ! ## Profitons !
Sonarqube a repéré quelques erreurs dans le code de `youp0m`, essayez de les Sonarqube a repéré quelques erreurs dans le code de `youp0m`, essayez de les
corriger, et publiez une nouvelle version, pour observer toute la chaîne en corriger, et publiez une nouvelle version, pour observer toute la chaîne en
action ! action !

View file

@ -6,7 +6,7 @@ Mettons de côté le déploiement continu, pour nous concentrer sur la manière
dont nous allons pouvoir exécuter notre module de relevé de compteur Linky. dont nous allons pouvoir exécuter notre module de relevé de compteur Linky.
\ \
Le binaire de notre module se lance de la manière suivante : Le binaire de notre module se lance de la manière suivante :
<div lang="en-US"> <div lang="en-US">
```shell ```shell
@ -35,7 +35,7 @@ retient votre attention.
Vous êtes tenu de retenir au minimum 2 solutions distinctes (on considère que Vous êtes tenu de retenir au minimum 2 solutions distinctes (on considère que
les technologies listées sur la même lignes sont similaires). les technologies listées sur la même lignes sont similaires).
La liste de technologies proposées est à la suivante : La liste de technologies proposées est à la suivante :
- conteneur Docker ou podman, - conteneur Docker ou podman,
- conteneur LXC (avec base alpine ou nu), - conteneur LXC (avec base alpine ou nu),
@ -83,7 +83,7 @@ login_x-TP5/lxc/run.sh
</div> </div>
En complément, vous pouvez inclure au dépôt de `linky2influx` le modèle En complément, vous pouvez inclure au dépôt de `linky2influx` le modèle
permettant de créer le conteneur LXC, ainsi qu'un exemple de configuration : permettant de créer le conteneur LXC, ainsi qu'un exemple de configuration :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -107,7 +107,7 @@ vous pourriez écrire le script `systemd` et profiter de l'utiliser dans votre
recette `bitbake`. recette `bitbake`.
Un service basé sur `nspawn` peut par contre être potentiellement intéressant, Un service basé sur `nspawn` peut par contre être potentiellement intéressant,
il pourra être intégré au dépôt : il pourra être intégré au dépôt :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -121,7 +121,7 @@ login_x-TP5/linky2influx/systemd/linky2influx.nspawn
Vous pourriez vouloir écrire une recette Bitbake pour créer et déployer le Vous pourriez vouloir écrire une recette Bitbake pour créer et déployer le
module via un paquet `.ipk` ou similaire en fonction de votre configuration. module via un paquet `.ipk` ou similaire en fonction de votre configuration.
Écrivez la recette au sein de `meta-electropcool` : Écrivez la recette au sein de `meta-electropcool` :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -146,7 +146,7 @@ utiliser le package Nix ensuite.
### Snap, Flatpack, AppImage ### Snap, Flatpack, AppImage
Intégrez au dépôt le fichier de description, par exemple : Intégrez au dépôt le fichier de description, par exemple :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -155,7 +155,7 @@ login_x-TP5/linky2influx/snapcraft.yaml
</div> </div>
Il faudra également préciser avec un fichier `run.sh` la manière dont lancer Il faudra également préciser avec un fichier `run.sh` la manière dont lancer
votre conteneur : votre conteneur :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -168,7 +168,7 @@ login_x-TP5/{snap,flatpack}/run.sh
### k3s ### k3s
Nous en apprendrons davantage sur Kubernetes au prochain TP, mais si vous Nous en apprendrons davantage sur Kubernetes au prochain TP, mais si vous
connaissez déjà, vous pourriez vouloir écrire un *Chart* Helm : connaissez déjà, vous pourriez vouloir écrire un *Chart* Helm :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -176,7 +176,7 @@ login_x-TP5/k3s/linky2influx.yaml
``` ```
</div> </div>
Inutile de vous casser la tête avec ça si vous ne connaissez pas ! Inutile de vous casser la tête avec ça si vous ne connaissez pas !
### Votre solution ### Votre solution
@ -191,4 +191,4 @@ login_x-TP5/k3s/linky2influx.yaml
</div> </div>
\ \
À vous de jouer ! À vous de jouer !

View file

@ -1,5 +1,5 @@
Voici à quoi pourrait ressembler le playbook Ansible démarrant notre conteneur Voici à quoi pourrait ressembler le playbook Ansible démarrant notre conteneur
Drone : Drone :
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml

View file

@ -1,26 +1,36 @@
Voici à quoi pourrait ressembler la ligne de commande démarrant notre conteneur Tout comme Gitea, Drone tire un certain nombre de paramètres depuis son
Drone : environnement. Nous allons donc commencer par indiquer l'identifiant et le
secret de l'application que l'on a créé précédemment dans Gitea :
<div lang="en-US"> <div lang="en-US">
```shell ```shell
export DRONE_GITEA_CLIENT_ID=#FIXME export DRONE_GITEA_CLIENT_ID=#FIXME
export DRONE_GITEA_CLIENT_SECRET=#FIXME export DRONE_GITEA_CLIENT_SECRET=#FIXME
export DRONE_RPC_SECRET=$(openssl rand -base64 30)
docker container run --name droneci -d \
-v /var/lib/drone:/data \
--network gitea -p 80:80 \
-e DRONE_GITEA_CLIENT_ID -e DRONE_GITEA_CLIENT_SECRET -e DRONE_GITEA_SERVER=http://gitea:3000 \
-e DRONE_RPC_SECRET -e DRONE_SERVER_HOST=droneci -e DRONE_SERVER_PROTO=http \
drone/drone:1
docker network connect drone droneci
``` ```
</div> </div>
La dernière commande permet à notre conteneur Drone d'être à la fois présent Puis, tout comme pour Gitea, nous allons générer un secret. Ce secret est
dans le réseau `gitea` et `drone`, ce qui permet de garder les deux réseaux utilisé par les différents *worker*s pour s'authentifier :
distincts.
<div lang="en-US">
```shell
export DRONE_RPC_SECRET=$(openssl rand -base64 30)
```
</div>
Lançons enfin Drone avec les deux commandes suivantes :
<div lang="en-US">
```shell
docker volume create drone_data
docker container run --name droneci -d -v drone_data:/data --network my_ci_net
-p 80:80 -e DRONE_GITEA_CLIENT_ID -e DRONE_GITEA_CLIENT_SECRET \
-e DRONE_GITEA_SERVER=http://gitea:3000 -e DRONE_SERVER_PROTO=http \
-e DRONE_RPC_SECRET -e DRONE_SERVER_HOST=droneci \
drone/drone:2
```
</div>
Gardez la variable d'environnement `DRONE_RPC_SECRET` dans un coin, nous en Gardez la variable d'environnement `DRONE_RPC_SECRET` dans un coin, nous en
aurons encore besoin juste après. aurons encore besoin juste après.

View file

@ -1,15 +1,7 @@
::::: {.question} Une fois lancé, rendez-vous sur l'interface de DroneCI : <http://droneci/>
La version 2 de Drone, encore plus pratique et sympathique est disponible en
test. Vous pouvez tout à fait l'utiliser pour la suite du TP. Cela ne change
pas la version des *runners* à utiliser.
:::::
Une fois lancé, rendez-vous sur l'interface de DroneCI : <http://droneci/>
Vous serez automatiquement redirigé vers la page d'authentification de Gitea, Vous serez automatiquement redirigé vers la page d'authentification de Gitea,
puis vers l'autorisation OAuth d'accès de Drone à Gitea. Il faut bien puis vers l'autorisation OAuth d'accès de Drone à Gitea. Il faut bien
évidemment valider cette demande, afin que Drone ait accès à nos dépôts. évidemment valider cette demande, afin que Drone ait accès à nos dépôts.
![OAuth Drone](../devops/oauth-drone.png){width=9cm} ![OAuth Drone](../devops/oauth-drone.png){width=9cm}

View file

@ -1,4 +1,4 @@
Voici à quoi pourrait ressembler le playbook Ansible démarrant notre agent Drone : Voici à quoi pourrait ressembler le playbook Ansible démarrant notre agent Drone :
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml

View file

@ -1,11 +1,13 @@
Voici à quoi pourrait ressembler la ligne de commande démarrant notre agent Drone : \
Voici La ligne de commande permettant de démarrer notre agent :
<div lang="en-US"> <div lang="en-US">
```shell ```shell
docker container run --name droneci-runner -d \ docker container run --name droneci-runner -d --network my_ci_net \
-v /var/run/docker.sock:/var/run/docker.sock --network drone \ -v /var/run/docker.sock:/var/run/docker.sock -e DRONE_RPC_PROTO=http
-e DRONE_RPC_PROTO=http -e DRONE_RPC_HOST=droneci -e DRONE_RPC_SECRET \ -e DRONE_RPC_HOST=droneci -e DRONE_RPC_SECRET -e DRONE_RUNNER_CAPACITY=2 \
-e DRONE_RUNNER_CAPACITY=2 -e DRONE_RUNNER_NAME=my-runner -e DRONE_RUNNER_NETWORKS=drone,gitea \ -e DRONE_RUNNER_NAME=my-runner -e DRONE_RUNNER_NETWORKS=my_ci_net \
drone/drone-runner-docker:1 drone/drone-runner-docker:1
``` ```
</div> </div>

View file

@ -0,0 +1,9 @@
::::: {.more}
On remarquera que l'on partage notre socket Docker : l'exécution de code
arbitraire n'aura pas lieu directement dans le conteneur, en fait il s'agit
d'un petit orchetrateur qui lancera d'autres conteneurs en fonction des tâches
qu'on lui demandera. Le code arbitraire sera donc toujours exécuté dans un
conteneur moins privilégié.
:::::

View file

@ -2,14 +2,13 @@
Notre conteneur `droneci` est uniquement une interface graphique qui va Notre conteneur `droneci` est uniquement une interface graphique qui va
centraliser d'un côté les nouveaux commits à traiter, et de l'autre les centraliser d'un côté les nouveaux commits à traiter, et de l'autre les
résultats retournés par les agents chargés d'exécuter le code. résultats retournés par les agents chargés d'exécuter les tâches.
Il serait impensable d'exécuter arbitrairement du code en parallèle d'une Il serait impensable d'exécuter arbitrairement du code en parallèle d'une
application privilégiée (ici, notre conteneur `droneci` a accès aux dépôts application privilégiée (ici, notre conteneur `droneci` a accès aux dépôts
potentiellement privés de Gitea). Les agents qui sont amenés à traiter du code potentiellement privés de Gitea). Les agents qui sont amenés à traiter du code
arbitraire s'exécutent à part et peuvent être de différents types. Dans le arbitraire s'exécutent à part et peuvent être de différents types.
vocabulaire de Drone, on les appelle des ~~blade~~*runners*.
Nous allons lancer un *runner* Docker : il s'agit d'un type d'agent qui va Nous allons lancer un *runner* Docker : il s'agit d'un type d'agent qui va
exécuter nos étapes de compilation dans des conteneurs Docker (oui, quand on exécuter nos étapes de compilation dans des conteneurs Docker (oui, quand on
disait que Drone était conçu autour de Docker, c'était pas pour rire !) disait que Drone était conçu autour de Docker, c'était pas pour rire !)

View file

@ -8,6 +8,10 @@ Mais nous allons déployer notre propre solution, en utilisant [Drone
CI](https://drone.io/). C'est une solution d'intégration continue libre et CI](https://drone.io/). C'est une solution d'intégration continue libre et
moderne, conçue tout autour de Docker. Idéale pour nous ! moderne, conçue tout autour de Docker. Idéale pour nous !
Deux conteneurs sont à lancer : nous aurons d'un côté l'interface de contrôle
et de l'autre un agent (*runner* dans le vocabulaire de Drone) chargé
d'exécuter les tests. Dans un environnement de production, on aura généralement
plusieurs agents, et ceux-ci seront situé sur des machines distinctes.
### Interface de contrôle et de dispatch des tâches ### Interface de contrôle et de dispatch des tâches
@ -19,6 +23,8 @@ Drone va avoir besoin d'authentifier les utilisateurs afin d'accéder aux dépô
privés (avec l'autorisation des utilisateurs). Pour cela, comme l'indique la privés (avec l'autorisation des utilisateurs). Pour cela, comme l'indique la
documentation de Drone, on va utiliser OAuth2 : dans Gitea, il va falloir créer documentation de Drone, on va utiliser OAuth2 : dans Gitea, il va falloir créer
une *application OAuth2*. Le formulaire de création se trouve dans la une *application OAuth2*. Le formulaire de création se trouve dans la
configuration du compte utilisateur, sous l'onglet *Applications*. Drone aura configuration du compte utilisateur, sous l'onglet *Applications*.
également besoin d'une URL de redirection. Dans notre cas, ce sera :
Drone aura également besoin d'une URL de redirection. Dans notre cas,
ce sera :\
`http://droneci/login`. `http://droneci/login`.

View file

@ -1 +1 @@
L'environnement étant prêt, il ne reste plus qu'à nous lancer dans nos projets ! L'environnement étant prêt, il ne reste plus qu'à nous lancer dans nos projets !

View file

@ -1,13 +1,17 @@
Votre playbook ressemblera à quelque chose comme ça : Votre playbook ressemblera à quelque chose comme ça :
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml
- name: Launch gitea container - name: Create a volume for storing repositories
docker_volume:
name: gitea-data
- name: launch gitea container
docker_container: docker_container:
name: gitea name: gitea
image: "gitea/gitea:{{ version }}" image: "gitea/gitea:{{ version }}"
volumes: volumes:
- /var/lib/gitea:/data - gitea-data:/data
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro - /etc/timezone:/etc/timezone:ro
state: started state: started
@ -27,3 +31,5 @@ Votre playbook ressemblera à quelque chose comme ça :
SECRET_KEY: "{{ secret_key }}" SECRET_KEY: "{{ secret_key }}"
``` ```
</div> </div>
Plus d'infos sur cette page : <https://docs.gitea.io/en-us/install-with-docker/>.

View file

@ -1,13 +1,33 @@
La ligne de commande pour lancer Gitea ressemblera à quelque chose comme ça : Commençons par créer un nouveau volume `gitea-data`, celui-ci contiendra
les données de `gitea` (nos dépôts Git, mais également la configuration propre
à `gitea`) :
<div lang="en-US">
```shell
docker volume create gitea-data
```
</div>
Afin de simplifier l'installation de notre conteneur, nous allons utiliser un
maximum de paramètres par défaut. Il faudra toutefois générer une clef secrète
propre à l'installation. Puisque c'est temporaire, on peut se contenter de ne
pas la stocker (elle sera perdue si on ferme notre terminal) :
<div lang="en-US"> <div lang="en-US">
```shell ```shell
export SECRET_KEY=$(openssl rand -base64 30) export SECRET_KEY=$(openssl rand -base64 30)
```
</div>
docker container run --name gitea -d \ Pour finir, lançons notre conteneur `gitea` :
-v /var/lib/gitea:/data -v /etc/timezone:/etc/timezone:ro -v /etc/localtime:/etc/localtime:ro \
--network gitea -p 2222:22 -p 3000:3000 \ <div lang="en-US">
-e RUN_MODE=prod -e DOMAIN=gitea -e SSH_DOMAIN=gitea -e INSTALL_LOCK=true -e SECRET_KEY \ ```shell
docker container run --name gitea --network my_ci_net -p 2222:22 -p 3000:3000 \
-v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro \
-v gitea-data:/data \
-e RUN_MODE=prod -e DOMAIN=gitea -e SSH_DOMAIN=gitea -e INSTALL_LOCK=true \
-e SECRET_KEY -d \
gitea/gitea:1 gitea/gitea:1
``` ```
</div> </div>

View file

@ -1,15 +1,15 @@
Plus d'infos sur cette page : <https://docs.gitea.io/en-us/install-with-docker/>. Une fois le conteneur lancé, vous pouvez accéder à l'interface de votre
gestionnaire de versions sur le port 3000 de votre machine (à moins que vous
n'ayez opté pour un autre port).
\
Une fois le conteneur lancé, vous pouvez accéder à l'interface de gitea sur le Vous pouvez ajouter un nouvel administrateur avec la commande suivante :
port 3000 de votre machine (à moins que vous n'ayez opté pour un autre port).
Vous pouvez ajouter un nouvel administrateur avec la commande suivante :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
docker exec gitea gitea admin user create --username "${USER}" --random-password \ docker exec gitea gitea admin user create --username "${USER}" --admin \
--must-change-password=false --admin --email "${USER}@epita.fr" --must-change-password=false --random-password --email "${USER}@example.com"
``` ```
</div> </div>
Notez le mot de passe généré pour [vous y connecter](http://localhost:3000/user/login). Notez le mot de passe généré pour ensuite vous y connecter.

View file

@ -21,7 +21,7 @@ que l'on peut lier avec ses dépôts. Une fonctionnalité que GitLab propose
En effet, la problématique du stockage des produits de compilation est En effet, la problématique du stockage des produits de compilation est
vaste. Si au début on peut se satisfaire d'un simple serveur web/FTP/SSH pour vaste. Si au début on peut se satisfaire d'un simple serveur web/FTP/SSH pour
les récupérer manuellement, on a vite envie de pouvoir utiliser les outils les récupérer manuellement, on a vite envie de pouvoir utiliser les outils
standards directement : `docker pull ...`, `npm install ...`, ... standards directement : `docker pull ...`, `npm install ...`, ...
Des programmes et services se sont spécialisés là-dedans, citons notamment Des programmes et services se sont spécialisés là-dedans, citons notamment
[Artifactory](https://jfrog.com/artifactory/) ou [Nexus [Artifactory](https://jfrog.com/artifactory/) ou [Nexus
@ -33,11 +33,11 @@ Dans un premier temps, nous allons nous contenter de publier un binaire associé
### Installation et configuration ### Installation et configuration
Allez c'est parti ! première chose à faire : installer et configurer Allez c'est parti ! première chose à faire : installer et configurer
[Gitea](https://gitea.io/) (ceux qui le souhaitent peuvent choisir [Gitea](https://gitea.io/) (ceux qui le souhaitent peuvent choisir
[gitlab](https://gitlab.org/) ou une autre plate-forme, mais la suite sera [gitlab](https://gitlab.org/) ou une autre plate-forme, mais la suite sera
moins guidée). moins guidée).
Nous allons utiliser l'image : Nous allons utiliser l'image :
[`gitea/gitea`](https://hub.docker.com/r/gitea/gitea) (ou [`gitea/gitea`](https://hub.docker.com/r/gitea/gitea) (ou
[`gitlab/gitlab-ce`](https://hub.docker.com/r/gitlab/gitlab-ce)). [`gitlab/gitlab-ce`](https://hub.docker.com/r/gitlab/gitlab-ce)).

View file

@ -0,0 +1,16 @@
## Préparer le terrain
Tous les déploiements sont à faire sur votre machine en utilisant des
conteneurs Docker, qui seront regroupés au sein de réseaux
Docker. Cela vous permettra dutiliser la résolution de noms entre vos
conteneurs.
Dans votre playbook Ansible, vous pourrez procéder ainsi :
<div lang="en-US">
```yaml
- name: Create virli network
docker_network:
name: virli3
```
</div>

View file

@ -0,0 +1,15 @@
## Préparer le terrain
Tous les déploiements sont à faire sur votre machine ; la plate-forme de CI
utilisera massivement les conteneurs Docker, qui seront regroupés au sein de
réseaux Docker : cela nous permettra de profiter de la résolution de noms entre
les conteneurs.
Dès à présent, nous pouvons commencer par créer un réseau, dans lequel nous
placerons tous nos conteneurs de CI/CD :
<div lang="en-US">
```shell
docker network create my_ci_net
```
</div>

View file

@ -3,7 +3,7 @@
Électropcool Électropcool
============ ============
Bienvenue dans la société Électropcool ! Bienvenue dans la société Électropcool !
Électropcool est une société française spécialisée dans Électropcool est une société française spécialisée dans
l'[immotique](https://fr.wikipedia.org/wiki/Immotique), elle vend des l'[immotique](https://fr.wikipedia.org/wiki/Immotique), elle vend des
@ -20,14 +20,14 @@ en combustible (liés à la météo)[^HOMEASSISTANT].
[^HOMEASSISTANT]: Si ça vous met l'eau à la bouche, jettez un œil du côté du [^HOMEASSISTANT]: Si ça vous met l'eau à la bouche, jettez un œil du côté du
projet <https://www.home-assistant.io/> qui fait un peu moins de projet <https://www.home-assistant.io/> qui fait un peu moins de
*bullshit*, mais est bien réel ! *bullshit*, mais est bien réel !
La principale difficulté que rencontre Électropcool est qu'aucun bâtiment ne La principale difficulté que rencontre Électropcool est qu'aucun bâtiment ne
dispose des mêmes références de pièces et qu'en dehors des nouveaux bâtiments dispose des mêmes références de pièces et qu'en dehors des nouveaux bâtiments
pour lesquels la société peut imposer des équipements électroniques pour lesquels la société peut imposer des équipements électroniques
spécifiquement supportés et compatibles avec la plate-forme qu'elle vend, il lui spécifiquement supportés et compatibles avec la plate-forme qu'elle vend, il lui
est bien souvent nécessaire de faire des développements spécifiques pour est bien souvent nécessaire de faire des développements spécifiques pour
s'interfacer avec de l'électronique existant : c'est notamment le cas pour les s'interfacer avec de l'électronique existant : c'est notamment le cas pour les
chaudières et les chaudières et les
[VMC](https://fr.wikipedia.org/wiki/Ventilation_m%C3%A9canique_contr%C3%B4l%C3%A9e), [VMC](https://fr.wikipedia.org/wiki/Ventilation_m%C3%A9canique_contr%C3%B4l%C3%A9e),
qui, compte tenu de leur coût de remplacement prohibitif, nécessitent souvent qui, compte tenu de leur coût de remplacement prohibitif, nécessitent souvent
@ -74,7 +74,7 @@ retiendrez.)
\ \
Le projet qui vous servira de base pour vos tests sera Le projet qui vous servira de base pour vos tests sera
[`linky2influx`](https://git.nemunai.re/nemunaire/linky2influx) : à partir d'un [`linky2influx`](https://git.nemunai.re/nemunaire/linky2influx) : à partir d'un
compteur [Linky](https://fr.wikipedia.org/wiki/Linky), branché sur les bornes compteur [Linky](https://fr.wikipedia.org/wiki/Linky), branché sur les bornes
de [téléinformation client du de [téléinformation client du
compteur](https://hallard.me/demystifier-la-teleinfo/) et [lisant le compteur](https://hallard.me/demystifier-la-teleinfo/) et [lisant le
@ -92,36 +92,3 @@ gestionnaire de versions.
Nous testerons enfin différentes solution pour déployer notre binaire, afin Nous testerons enfin différentes solution pour déployer notre binaire, afin
d'établir quelle est la solution adéquate. d'établir quelle est la solution adéquate.
## Préparer le terrain
Tous les déploiements sont à faire sur votre machine et la plate-forme de CI
utilisera massivement les conteneurs Docker, qui seront regroupés au sein de
réseaux Docker. Cela vous permettra d'utiliser la résolution de noms entre vos
conteneurs.
Vous devriez dès maintenant créer les deux réseaux suivants sur votre machines :
<div lang="en-US">
```shell
docker network create gitea
docker network create drone
```
</div>
Étant donné que votre machine ne dispose pas de domaine sur Internet et que
l'on va essayer de simplifier au maximum l'installation, vous devriez ajouter
cette ligne à votre fichier `/etc/hosts` (ou
`\Windows\System32\drivers\etc\hosts`) :
<div lang="en-US">
```conf
127.0.0.1 gitea droneci
```
</div>
Cette ligne va vous permettre de résoudre les noms des conteneurs. Cela
permettra aux requêtes OAuth de se faire de manière transparente pour vous
lorsque vous serez dans votre navigateur.

View file

@ -0,0 +1,14 @@
Étant donné que votre machine ne dispose pas de domaine sur Internet et que
l'on va essayer de simplifier au maximum l'installation, vous devriez ajouter
cette ligne à votre fichier `/etc/hosts` (ou
`\Windows\System32\drivers\etc\hosts`) :
<div lang="en-US">
```conf
127.0.0.1 gitea droneci
```
</div>
Cette ligne va vous permettre de résoudre les noms des conteneurs. Cela
permettra aux requêtes OAuth de se faire de manière transparente pour vous
lorsque vous serez dans votre navigateur.

View file

@ -0,0 +1,32 @@
\newpage
But du TP
=========
Nous allons nous mettre aujourdhui dans la peau dune équipe DevOps et
réaliser une solution complète dintégration/déploiement continu (le fameux
CI/CD, pour *Continuous Integration* et *Continuous Delivery*).
Le résultat attendu dici la fin de cette partie sera de mettre en place toutes
les briques décrites dans la section précédente.
\
Nous allons commencer par automatiser le projet `youp0m`, plus simple, ~~puis
la plate-forme du FIC dans son ensemble, ce qui représente un petit challenge~~
(merci Nabih !).
Il est également attendu que vous rendiez un playbook Ansible, permettant de
retrouver un environnement similaire. Car on pourra sen resservir par la
suite.
\
Dans un premier temps, on voudra juste compiler notre projet, pour sassurer
que chaque commit poussé ne contient pas derreur de compilation, dans
lenvironnement défini comme étant celui de production. Ensuite, on ajoutera
quelques tests automatiques. Puis nous publierons automatiquement le binaire
`youp0m` comme fichier associé à un tag au sein de linterface web du
gestionnaire de versions.
Enfin, nous mettrons en place un registre Docker qui nous permettra de publier
automatiquement limage Docker associée. Cest à partir de cette image Docker
que lon va commencer à déployer automatiquement...

View file

@ -1,64 +1,25 @@
\newpage \newpage
But du TP La journée DevOps
========= =================
Nous allons nous mettre aujourd'hui dans la peau d'une équipe DevOps et Nous allons maintenant nous mettre dans la peau d'une équipe DevOps et
réaliser une solution complète d'intégration/déploiement continu (le fameux réaliser une solution complète d'intégration/déploiement continu (le fameux
CI/CD, pour *Continuous Integration* et *Continuous Delivery*). CI/CD, pour *Continuous Integration* et *Continuous Delivery*).
Le résultat attendu d'ici la fin de cette partie sera de mettre en place toutes Le résultat attendu d'ici la fin de cette partie sera de mettre en place toutes
les briques décrites dans la section précédente. les briques décrites au chapitre précédent. Nous allons pour cela automatiser
\ le projet `youp0m`, que l'on connaît déjà bien.
Nous allons commencer par automatiser le projet `youp0m`, plus simple, ~~puis
la plate-forme du FIC dans son ensemble, ce qui représente un petit challenge~~
(merci Nabih !).
Il est également attendu que vous rendiez un playbook Ansible, permettant de
retrouver un environnement similaire. Car on pourra s'en resservir par la suite.
\ \
Dans un premier temps, on voudra juste compiler notre projet, pour s'assurer Dans un premier temps, on voudra juste compiler notre projet, pour s'assurer
que chaque commit poussé ne contient pas d'erreur de compilation, dans que chaque *commmit* poussé ne contient pas d'erreur de compilation (dans
l'environnement défini comme étant celui de production. Ensuite, on ajoutera l'environnement défini comme étant celui de production, donc avec une version
quelques tests automatiques. Puis nous publierons automatiquement le binaire précise des outils de compilation). Ensuite, nous ajouterons quelques tests
`youp0m` comme fichier associé à un tag au sein de l'interface web du automatiques, puis nous publierons automatiquement le binaire `youp0m` comme
gestionnaire de versions. fichier associé à un tag au sein de l'interface web d'un gestionnaire de
versions.
Enfin, nous mettrons en place un registre Docker qui nous permettra de publier Enfin, nous mettrons en place un registre Docker qui nous permettra de publier
automatiquement l'image Docker associée. C'est à partir de cette image Docker automatiquement l'image Docker associée. C'est à partir de cette image Docker
que l'on va commencer à déployer automatiquement... que l'on va commencer à déployer automatiquement...
## Préparer le terrain
Tous les déploiements sont à faire sur votre machine en utilisant des
conteneurs Docker, qui seront regroupés au sein de réseaux Docker. Cela vous
permettra d'utiliser la résolution de noms entre vos conteneurs.
Dans votre playbook Ansible, vous pourrez procéder ainsi :
<div lang="en-US">
```yaml
- name: Create virli network
docker_network:
name: virli3
```
</div>
Étant donné que votre machine ne dispose pas de domaine sur Internet et que
l'on va essayer de simplifier au maximum l'installation, vous devriez ajouter
cette ligne à votre fichier `/etc/hosts` (ou
`\Windows\System32\drivers\etc\hosts`) :
<div lang="en-US">
```conf
127.0.0.1 gitea droneci
```
</div>
Cette ligne va vous permettre de résoudre les noms des conteneurs. Cela
permettra aux requêtes OAuth de se faire de manière transparente pour vous
lorsque vous serez dans votre navigateur.

View file

@ -57,7 +57,7 @@ run`.
Cette section est le pendant de la commandes `docker volume`. Cette section est le pendant de la commandes `docker volume`.
On déclare les volumes simplement en leur donnant un nom et un driver comme On déclare les volumes simplement en leur donnant un nom et un driver comme
suit : suit:
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml
@ -68,7 +68,7 @@ volumes:
</div> </div>
Pour les utiliser avec un conteneur, on référence le nom ainsi que Pour les utiliser avec un conteneur, on référence le nom ainsi que
l'emplacement à partager : l'emplacement à partager:
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml
@ -87,10 +87,10 @@ Cette section est le pendant de la commandes `docker network`.
Par défaut, Docker relie tous les conteneurs sur un bridge et fait du NAT pour Par défaut, Docker relie tous les conteneurs sur un bridge et fait du NAT pour
que les conteneurs puissent accéder à l'Internet. Mais ce n'est pas le seul que les conteneurs puissent accéder à l'Internet. Mais ce n'est pas le seul
mode possible ! mode possible!
De la même manière que pour les `volumes`, cette section déclare les réseaux De la même manière que pour les `volumes`, cette section déclare les réseaux
qui pourront être utilisés par les `services`. On pourrait donc avoir : qui pourront être utilisés par les `services`. On pourrait donc avoir:
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml
@ -133,12 +133,14 @@ lié, même après que l'on ait démarré. La résolution se fera dynamiquement.
#### Utiliser le `docker-compose.yml` #### Utiliser le `docker-compose.yml`
Consultez Consultez la documentation[^COMPOSEDOC] pour une liste exhaustive des options
[la documentation](https://docs.docker.com/compose/compose-file/) pour que nous pouvons utiliser.
une liste exhaustive des options que nous pouvons utiliser.
[^COMPOSEDOC]: La documentation des `docker-compose.yml`:
<https://docs.docker.com/compose/compose-file/>
Une fois que notre `docker-compose.yml` est prêt, nous pouvons lancer Une fois que notre `docker-compose.yml` est prêt, nous pouvons lancer
la commande suivante et admirer le résultat : la commande suivante et admirer le résultat:
<div lang="en-US"> <div lang="en-US">
```bash ```bash

View file

@ -6,9 +6,8 @@ Lier des conteneurs
Avant de voir des méthodes plus automatiques pour déployer toute notre pile Avant de voir des méthodes plus automatiques pour déployer toute notre pile
logicielle TICK, nous allons commencer par mettre en place et lier les logicielle TICK, nous allons commencer par mettre en place et lier les
conteneurs manuellement, de la même manière que nous avons pu le faire avec conteneurs manuellement, de la même manière que nous avons pu le faire avec
l'interface d'administration du FIC et MySQL. Cela nous permettra de voir les MySQL. Cela nous permettra de voir les subtilités de chaque image, ce qui nous
subtilités de chaque image, ce qui nous fera gagner du temps pour ensuite fera gagner du temps pour ensuite en faire la description.
en faire la description.
### Conteneur central: la base de données ### Conteneur central: la base de données
@ -58,7 +57,8 @@ le client officiel (le binaire s'appelle `influx`):
<div lang="en-US"> <div lang="en-US">
``` ```
42sh$ docker container run --rm -it --link mytsdb:influxdb influxdb:1.8 influx -host influxdb 42sh$ docker container run --rm -it --link mytsdb:influxdb influxdb:1.8 \
influx -host influxdb
Connected to http://influxdb:8086 version 1.8.9 Connected to http://influxdb:8086 version 1.8.9
InfluxDB shell version: 1.8.9 InfluxDB shell version: 1.8.9
> show databases > show databases
@ -69,10 +69,10 @@ _internal
``` ```
</div> </div>
Si vous aussi vous voyez la table `_internal`, bravo ! vous pouvez passer à la Si vous aussi vous voyez la table `_internal`, bravo! vous pouvez passer à la
suite. suite.
#### Mais quelle était cette commande magique ? {-} #### Mais quelle était cette commande magique? {-}
Oui, prenons quelques minutes pour l'analyser... Oui, prenons quelques minutes pour l'analyser...
@ -132,7 +132,9 @@ système. Pour cela, on commence par télécharger *Telegraf*:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
curl https://dl.influxdata.com/telegraf/releases/telegraf-1.19.2_linux_amd64.tar.gz | \ V=1.19.2
P=telegraf-${V}_linux_$(uname -m)
curl https://dl.influxdata.com/telegraf/releases/${P}.tar.gz | \
tar xzv -C /tmp tar xzv -C /tmp
``` ```
</div> </div>
@ -157,7 +159,8 @@ Et observons ensuite:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
42sh$ docker container run --rm -it --link mytsdb:zelda influxdb:1.8 influx -host zelda 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.9
> show databases > show databases
name: databases name: databases
@ -205,6 +208,6 @@ si besoin.
la page d'accueil est vide au démarrage, pour savoir si vous avez réussi, la page d'accueil est vide au démarrage, pour savoir si vous avez réussi,
rendez-vous sous l'onglet *Hosts*, le nom de votre machine devrait y rendez-vous sous l'onglet *Hosts*, le nom de votre machine devrait y
apparaître. En cliquant dessus, vous obtiendrez des graphiques similaires à apparaître. En cliquant dessus, vous obtiendrez des graphiques similaires à
ceux ci-dessous: ceux ci-après:
![Résultat obtenu](chronograf_latest.png) ![Résultat obtenu](chronograf_latest.png)

View file

@ -7,7 +7,7 @@ Projet
------ ------
Réalisez le `docker-compose.yml` permettant de lancer toute notre stack de Réalisez le `docker-compose.yml` permettant de lancer toute notre stack de
monitoring, d'un simple : monitoring, d'un simple:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -49,10 +49,10 @@ Tarball
------- -------
Tous les fichiers identifiés comme étant à rendre pour ce TP sont à Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...). placer dans une tarball (pas d'archive ZIP, RAR, ...).
Voici une arborescence type (vous pourriez avoir des fichiers supplémentaires, Voici une arborescence type (vous pourriez avoir des fichiers supplémentaires,
cela dépendra de votre avancée dans le projet) : cela dépendra de votre avancée dans le projet):
<div lang="en-US"> <div lang="en-US">
``` ```
@ -66,7 +66,7 @@ login_x-TP1/...
## Signature du rendu ## Signature du rendu
Deux méthodes sont utilisables pour signer votre rendu : Deux méthodes sont utilisables pour signer votre rendu:
* signature du courriel ; * signature du courriel ;
* signature de la tarball. * signature de la tarball.
@ -93,7 +93,7 @@ signature.
#### No public key #### No public key
Si vous recevez un rapport avec l'erreur suivante : Si vous recevez un rapport avec l'erreur suivante:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -116,7 +116,7 @@ rendu.
#### Not explicit username #### Not explicit username
Si vous recevez un rapport avec l'erreur suivante : Si vous recevez un rapport avec l'erreur suivante:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -131,7 +131,7 @@ données.
#### I've decided to skip your e-mail #### I've decided to skip your e-mail
Si vous recevez un rapport concluant ainsi : Si vous recevez un rapport concluant ainsi:
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -5,7 +5,7 @@ Contenir les applications pour éviter les fuites
Lorsque l'on gère un environnement de production, on souhaite bien Lorsque l'on gère un environnement de production, on souhaite bien
évidemment éviter tout déni de service. Ou parfois, contenir un évidemment éviter tout déni de service. Ou parfois, contenir un
programme métier avec une fuite mémoire, dans certaines limites : il programme métier avec une fuite mémoire, dans certaines limites: il
vaut parfois mieux le tuer et le relancer automatiquement, plutôt que vaut parfois mieux le tuer et le relancer automatiquement, plutôt que
d'attendre que potentiellement un autre processus se fasse tuer à sa d'attendre que potentiellement un autre processus se fasse tuer à sa
place. place.
@ -44,7 +44,7 @@ l'ordonnanceur privilégiant alors les autres processus du système.
Par défaut, le taux maximal (1024 = 100%) d'utilisation CPU est donné Par défaut, le taux maximal (1024 = 100%) d'utilisation CPU est donné
aux nouveaux conteneurs, on peut le réduire en utilisant l'option aux nouveaux conteneurs, on peut le réduire en utilisant l'option
`-c`/`--cpu-shares` : 512 = 50%, par exemple. `-c`/`--cpu-shares`: 512 = 50%, par exemple.
## Sécuriser l'exécution ## Sécuriser l'exécution
@ -76,14 +76,14 @@ du noyau, seccomp est un filtre que l'on peut définir pour chaque
appel système. Liste blanche, liste noire, tout est possible. appel système. Liste blanche, liste noire, tout est possible.
Docker filtre notamment tous les appels systèmes qui pourraient Docker filtre notamment tous les appels systèmes qui pourraient
déborder à l'extérieur du conteneur : il n'est par exemple pas déborder à l'extérieur du conteneur: il n'est par exemple pas
possible de changer l'heure dans un conteneur, car il n'y a possible de changer l'heure dans un conteneur, car il n'y a
aujourd'hui aucun mécanisme pour isoler les visions des dates d'un aujourd'hui aucun mécanisme pour isoler les visions des dates d'un
conteneur à l'autre. conteneur à l'autre.
Voici par exemple un fichier de profil seccomp, interdisant Voici par exemple un fichier de profil seccomp, interdisant
l'utilisation de l'appel système `nanosleep(2)` (utilisé notamment par l'utilisation de l'appel système `nanosleep(2)` (utilisé notamment par
`sleep(1)`) : `sleep(1)`):
<div lang="en-US"> <div lang="en-US">
```js ```js
@ -105,11 +105,11 @@ l'utilisation de l'appel système `nanosleep(2)` (utilisé notamment par
``` ```
</div> </div>
On peut ensuite l'appliquer à un conteneur Docker : On peut ensuite l'appliquer à un conteneur Docker:
<div lang="en-US"> <div lang="en-US">
``` ```
42sh$ docker container run -it --security-opt seccomp=nanosleep.json ubuntu /bin/bash 42sh$ docker run -it --security-opt seccomp=nanosleep.json ubuntu /bin/bash
(cntnr)$ sleep 42 (cntnr)$ sleep 42
sleep: cannot read realtime clock: Operation not permitted sleep: cannot read realtime clock: Operation not permitted
``` ```

View file

@ -3,11 +3,10 @@
Mise en place Mise en place
------------- -------------
Dans la première partie du TP, nous avons installé l'environnement Docker Jusqu'ici, nous avons utilisé l'environnement Docker principal, qui inclut le
principal, qui inclut le client, le daemon et toute sa machinerie. Mais le client, le daemon et toute sa machinerie. Mais le projet Docker propose de
projet Docker propose de nombreuses autres ressources, souvent directement nombreuses extensions, souvent directement trouvées dans les usages de la
trouvées dans les usages de la communauté, et parfois même appropriées par communauté, et parfois même appropriées par Docker.
Docker.
### `docker-compose` ### `docker-compose`
@ -16,8 +15,8 @@ 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 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 être téléchargé séparément, car originellement, le projet était développé par
une équipe indépendante. Il constitue aujourd'hui une brique de l'écosystème une équipe indépendante (et en Python). Il constitue aujourd'hui une brique de
Docker, presque indispensable ! l'écosystème Docker, presque indispensable !
#### Par le gestionnaire de paquets #### Par le gestionnaire de paquets
@ -26,28 +25,17 @@ fonctionnera avec la version de Docker qu'ils fournissent.
#### Par la distribution binaire #### Par la distribution binaire
L'équipe en charge de Docker compose met à disposition un exécutable contenant L'équipe en charge du projet met à disposition un exécutable que nous pouvons
tous les scripts. Nous pouvons l'installer en suivant la procédure suivante : téléchargeant depuis <https://github.com/docker/compose/releases>.
<div lang="en-US"> Ajoutez l'exécutable dans le dossier des plugins : `$HOME/.docker/cli-plugins`
```bash (sans oublier de `chmod +x` !).
curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-x86_64 \
> /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose
```
</div>
#### `pip`
Le projet étant écrit en Python, il est également disponible via `pip`, si vous
préférez cette méthode. N'oubliez pas de préciser une version compatible avec
votre version de Docker.
#### Vérification du fonctionnement #### Vérification du fonctionnement
Comme avec Docker, nous pouvons vérifier le bon fonctionnement de Comme avec Docker, nous pouvons vérifier le bon fonctionnement de
`docker-compose` en exécutant la commande : `docker-compose` en exécutant la commande :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -56,13 +44,13 @@ docker-compose version: 1.29.2
``` ```
</div> </div>
Si vous obtenez une réponse similaire, c'est que vous êtes prêt à commencer le Si vous obtenez une réponse similaire, c'est que vous êtes prêt à continuer !
TP ! Alors n'attendons pas, partons à l'aventure ! Alors n'attendons pas, partons à l'aventure !
### Play With Docker ### Play With Docker
Tout comme pour la partie précédente, si vous avez des difficultés pour Tout comme pour la partie précédente, si vous avez des difficultés pour
réaliser les exercices sur vos machines, vous pouvez utiliser le projet [Play réaliser les exercices sur votre machine, vous pouvez utiliser le projet [Play
With Docker](https://play-with-docker.com/) qui vous donnera accès à un bac à With Docker](https://play-with-docker.com/) qui vous donnera accès à un bac à
sable avec lequel vous pourrez réaliser tous les exercices de ce TP. sable avec lequel vous pourrez réaliser tous les exercices.

View file

@ -6,7 +6,7 @@ institute: EPITA
date: Mercredi 2 octobre 2019 date: Mercredi 2 octobre 2019
abstract: | abstract: |
Dans cette deuxième partie du TP, nous allons apprendre à déployer Dans cette deuxième partie du TP, nous allons apprendre à déployer
un groupe de conteneurs ! un groupe de conteneurs !
\vspace{1em} \vspace{1em}

View file

@ -6,9 +6,9 @@ Orchestrer un groupe de conteneurs
Maintenant que nous savons démarrer individuellement des conteneurs et les lier Maintenant que nous savons démarrer individuellement des conteneurs et les lier
entre-eux, nous allons voir une première manière d'automatiser cela. entre-eux, nous allons voir une première manière d'automatiser cela.
Plutôt que de lancer les commandes `docker` comme nous l'avons fait jusque là : Plutôt que de lancer les commandes `docker` comme nous l'avons fait jusque là :
soit directement dans un terminal, soit via un script, nous allons décrire soit directement dans un terminal, soit via un script, nous allons décrire
l'état que nous souhaitons atteindre : quels images lancer, quels volumes l'état que nous souhaitons atteindre : quels images lancer, quels volumes
créer, quels réseaux, etc. Cette description peut s'utiliser pour lancer un créer, quels réseaux, etc. Cette description peut s'utiliser pour lancer un
conteneur seul, mais elle prend tout son sens lorsqu'il faut démarrer tout un conteneur seul, mais elle prend tout son sens lorsqu'il faut démarrer tout un
groupe de conteneurs qui fonctionnent de concert, parfois avec des dépendances groupe de conteneurs qui fonctionnent de concert, parfois avec des dépendances
@ -16,7 +16,7 @@ groupe de conteneurs qui fonctionnent de concert, parfois avec des dépendances
démarrer). démarrer).
On parle d'orchestration, car nous allons utiliser Docker comme un chef On parle d'orchestration, car nous allons utiliser Docker comme un chef
d'orchestre : il va ordonner les créations des différents objets (volumes, d'orchestre : il va ordonner les créations des différents objets (volumes,
réseaux, conteneurs, ...) afin d'arriver au résultat attendu, puis il va faire réseaux, conteneurs, ...) afin d'arriver au résultat attendu, puis il va faire
en sorte de maintenir ce résultat selon les événements qui pourront survenir. en sorte de maintenir ce résultat selon les événements qui pourront survenir.

View file

@ -1,6 +1,6 @@
include ../pandoc-opts.mk include ../pandoc-opts.mk
SOURCES = tutorial.md installation.md what.md first.md cleaning.md ex-flask.md volumes.md linking.md SOURCES = tutorial.md installation.md what.md first.md cleaning.md ex-flask.md volumes.md linking.md linking-ex-fic.md linking-ex-help.md
all: tutorial.pdf all: tutorial.pdf

View file

@ -17,19 +17,19 @@ l'option `--rm`.
### Conteneurs ### Conteneurs
Nous pouvons afficher l'ensemble des conteneurs, quel que soit leur état (en Nous pouvons afficher l'ensemble des conteneurs, quel que soit leur état (en
cours d'exécution, arrêtés,\ ...) avec la commande suivante : cours d'exécution, arrêtés, ...) avec la commande suivante:
<div lang="en-US"> <div lang="en-US">
``` ```
42sh$ docker container ls -a 42sh$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
552d71619723 hello-world "/hello" 4 days ago Exited (0) 4 days ago dreamy_gates 552d71619723 hello-world "/hello" 4 days ago Exited (0) 4 days ago dreamy_g
0e8bbff6d500 debian "/bin/bash" 2 weeks ago Exited (0) 2 weeks ago cranky_jones 0e8bbff6d500 debian "/bin/bash" 2 weeks ago Exited (0) 2 weeks ago cranky_j
``` ```
</div> </div>
Il y a de fortes chances pour que vous n'ayez plus besoin de ces vieux Il y a de fortes chances pour que vous n'ayez plus besoin de ces vieux
conteneurs. Pour les supprimer, utilisez la commande : conteneurs. Pour les supprimer, utilisez la commande:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -37,7 +37,7 @@ docker container rm 0e8bbff6d500 552d71619723
``` ```
</div> </div>
ou encore : ou encore:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -57,7 +57,7 @@ de la même manière que les conteneurs, avec les sous-commandes `docker image`.
### `prune` ### `prune`
Dans la plupart des menus permettant de gérer les objets Docker, vous trouverez Dans la plupart des menus permettant de gérer les objets Docker, vous trouverez
une commande `prune` qui supprimera les objets inutilisés : une commande `prune` qui supprimera les objets inutilisés:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -65,7 +65,7 @@ docker container prune
``` ```
</div> </div>
On aura tendance à vouloir supprimer tous les objets inutiles d'un seul coup, via : On aura tendance à vouloir supprimer tous les objets inutiles d'un seul coup, via:
<div lang="en-US"> <div lang="en-US">
```bash ```bash

View file

@ -2,3 +2,15 @@
Découvrons Docker Découvrons Docker
================= =================
Entrons sans plus attendre dans le vif du sujet: 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é. Aujourd'hui de nombreuses
entreprises n'hésitent plus à l'utiliser en production.
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
nous lancerons notre premier conteneur et nous irons jusqu'à déployer
un premier service web avec lequel nous pourrons interagir.

View file

@ -3,13 +3,13 @@
Mon premier webservice Mon premier webservice
---------------------- ----------------------
C'est parti, nous allons déployer notre premier service ! C'est parti, nous allons déployer notre premier service!
Il s'agit d'un service montrant une image aléatoire à chaque chargement de Il s'agit d'un service montrant une image aléatoire à chaque chargement de
page : <https://you.p0m.fr/>. page: <https://you.p0m.fr/>.
Nous pouvons télécharger et lancer le service grâce à : Nous pouvons télécharger et lancer le service grâce à:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -17,22 +17,22 @@ docker container run -i nemunaire/youp0m
``` ```
</div> </div>
Cette fois-ci, ce n'est pas un shell que nous obtenons[^defaultcmd] : il semblerait que le Cette fois-ci, ce n'est pas un shell que nous obtenons[^defaultcmd]: il semblerait que le
service soit lancé et écoute sur le port 8080. Est-ce le cas ? service soit lancé et écoute sur le port 8080. Est-ce le cas?
<http://localhost:8080> <http://localhost:8080>
[^defaultcmd]: Chaque conteneur dispose d'une commande par défaut : les images [^defaultcmd]: Chaque conteneur dispose d'une commande par défaut: les images
de base telles que les distributions vont lancer un shell, tandis que les de base telles que les distributions vont lancer un shell, tandis que les
conteneurs de service vont lancer leur service directement. conteneurs de service vont lancer leur service directement.
Non ! Car le service est contenerisé ! Il s'exécute dans son coin, sans Non! Car le service est contenerisé! Il s'exécute dans son coin, sans
interférer avec son hôte. interférer avec son hôte.
### Redirection de ports ### Redirection de ports
Nous pouvons rediriger le port avec l'argument <span lang="en-US">`-p dst_host:src_cntr`</span> : Nous pouvons rediriger le port avec l'argument <span lang="en-US">`-p dst_host:src_cntr`</span>:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -43,7 +43,7 @@ docker container run -i -p 8080:8080 nemunaire/youp0m
Cette fois, nous pouvons accéder au service. Cette fois, nous pouvons accéder au service.
Pour le moment, le service ne dispose d'aucune image à afficher, vous pouvez Pour le moment, le service ne dispose d'aucune image à afficher, vous pouvez
utiliser cette syntaxe pour ajouter une image : utiliser cette syntaxe pour ajouter une image:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -51,7 +51,7 @@ base64 monimage.jpg | curl --data @- http://localhost:8080/api/images/monimage
``` ```
</div> </div>
Si vous n'êtes pas particulièrement inspiré, vous pouvez ajouter ces images : Si vous n'êtes pas particulièrement inspiré, vous pouvez ajouter ces images:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -63,13 +63,13 @@ done
</div> </div>
### Prêt pour la production ? ### Prêt pour la production?
Avec l'option `-i`, nous pouvons encore transmettre les signaux de terminaison Avec l'option `-i`, nous pouvons encore transmettre les signaux de terminaison
au conteneur. C'est pratique lorsque l'on développe, mais en production, notre au conteneur. C'est pratique lorsque l'on développe, mais en production, notre
service ne s'exécutera pas dans notre terminal ! service ne s'exécutera pas dans notre terminal!
On utilise l'option `-d` pour lancer le conteneur en tâche de fond : On utilise l'option `-d` pour lancer le conteneur en tâche de fond:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -79,7 +79,7 @@ docker container run -d -p 8080:8080 nemunaire/youp0m
À partir de l'identifiant renvoyé par cette commande (que l'on peut également À partir de l'identifiant renvoyé par cette commande (que l'on peut également
obtenir avec un `docker container ls`), nous pouvons consulter les logs du obtenir avec un `docker container ls`), nous pouvons consulter les logs du
service (en fait, les sorties standard et d'erreur) : service (en fait, les sorties standard et d'erreur):
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -88,15 +88,15 @@ docker container logs 0123456789abcdef
</div> </div>
### Une autre instance ? ### Une autre instance?
Maintenant que nous avons un clone de <https://you.p0m.fr/>, nous voulons Maintenant que nous avons un clone de <https://you.p0m.fr/>, nous voulons
absolument un clone de <https://food.p0m.fr/> ! absolument un clone de <https://food.p0m.fr/>!
Il s'agit du même service, mais ce ne sont pas les mêmes images. 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, 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"> <div lang="en-US">
```bash ```bash
@ -104,10 +104,10 @@ docker container run -d -p 8081:8080 nemunaire/youp0m
``` ```
</div> </div>
Voyons le résultat : <http://localhost:8081> Voyons le résultat: <http://localhost:8081>
Nous avons réussi à lancer deux conteneurs à partir de la même image, et on Nous avons réussi à lancer deux conteneurs à partir de la même image, et on
voit bien que ceux-ci ne partagent pas leur système de fichiers : notre voit bien que ceux-ci ne partagent pas leur système de fichiers: notre
nouvelle instance est encore immaculée. nouvelle instance est encore immaculée.
@ -123,18 +123,19 @@ Outre les arguments que l'on peut passer au premier processus du conteneur, la
plupart des images peuvent adapter leur comportement en fonction de variables plupart des images peuvent adapter leur comportement en fonction de variables
d'environnement que l'on passe en paramètre. d'environnement que l'on passe en paramètre.
Cette bonne pratique est recommandée par <https://12factor.net/>, qui détaille Cette bonne pratique est recommandée par
les raisons qui devraient pousser les développeurs à privilégier les variables [`12factor.net`](https://12factor.net/), qui détaille les raisons qui devraient
d'environnements aux arguments sur la ligne de commande. pousser les développeurs à privilégier les variables d'environnements aux
arguments sur la ligne de commande.
Il se trouve que les conteneurs `youp0m` peuvent créer le fichier `htpasswd`, Il se trouve que les conteneurs `youp0m` peuvent créer le fichier `htpasswd`,
s'ils sont démarrés avec les variables d'environnement : s'ils sont démarrés avec les variables d'environnement:
- `YOUP0M_USERNAME` : nom d'utilisateur pour l'administrateur (par défaut admin) ; - `YOUP0M_USERNAME`: nom d'utilisateur pour l'administrateur (par défaut admin) ;
- `YOUP0M_PASSWORD` : mot de passe de l'utilisateur. - `YOUP0M_PASSWORD`: mot de passe de l'utilisateur.
Pour ajouter une variable d'environnement, cela se passe dans la commande Pour ajouter une variable d'environnement, cela se passe dans la commande
`run`, en ajoutant une ou plusieurs options `-e` : `run`, en ajoutant une ou plusieurs options `-e`:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -143,13 +144,14 @@ docker container run -e YOUP0M_PASSWORD=foobar -p 8080:8080 nemunaire/youp0m
</div> </div>
Une fois lancé, ce conteneur exposera une interface d'administration à cette Une fois lancé, ce conteneur exposera une interface d'administration à cette
adresse : <http://localhost:8080/admin/>. adresse:\
<http://localhost:8080/admin/>.
### Arrêt des conteneurs et persistance des données ### Arrêt des conteneurs et persistance des données
Lorsque l'on souhaite stopper un conteneur lancé en tâche de fond, on utilise Lorsque l'on souhaite stopper un conteneur lancé en tâche de fond, on utilise
son identifiant dans la commande suivante : son identifiant dans la commande suivante:
<div lang="en-US"> <div lang="en-US">
```bash ```bash

View file

@ -1,7 +1,5 @@
\newpage Exercice {-}
--------
Exercice
========
Pour mettre en pratiques toutes les notions que l'on a vu jusque là, écrivez un Pour mettre en pratiques toutes les notions que l'on a vu jusque là, écrivez un
script `mycloud-run.sh` pour automatiser le lancement de votre instance script `mycloud-run.sh` pour automatiser le lancement de votre instance
@ -16,25 +14,26 @@ pour se rendre sur la page de connexion. Une autre machine de votre réseau
local devrait également pouvoir accéder à la plate-forme, simplement en local devrait également pouvoir accéder à la plate-forme, simplement en
renseignant l'IP de votre machine et en ajoutant éventuellement des règles de renseignant l'IP de votre machine et en ajoutant éventuellement des règles de
pare-feu (mais cette dernière partie n'est pas demandée, gardez simplement en 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 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). 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 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 dans la (ie. sans utiliser `docker-compose` ou `docker stack` que l'on verra par la
seconde partie). Il pourra cependant faire usage des commandes `docker OBJECT suite). Il pourra cependant faire usage des commandes `docker OBJECT inspect`
inspect` pour ne pas avoir à faire d'analyse syntaxique sur les retours des pour ne pas avoir à faire d'analyse syntaxique sur les retours des commandes
commandes lisibles par les humains. lisibles par les humains.
Cette instance devra utiliser une base de données MySQL (lancée par vos soins Cette instance devra utiliser une base de données MySQL (lancée par votre
dans un autre conteneur) et contenir ses données dans un ou plusieurs volumes script dans un autre conteneur) et contenir ses données dans un ou plusieurs
(afin qu'elles persistent à une mise à jour des conteneurs par exemple). volumes (afin qu'elles persistent à une mise à jour des conteneurs par
exemple).
L'exécution doit être la plus sécurisée possible (pas de port MySQL exposé sur L'exécution doit être la plus sécurisée possible (pas de port MySQL exposé sur
l'hôte par exemple, etc.) et la plus respectueuse des bonnes pratiques que l'on l'hôte par exemple, etc.) et la plus respectueuse des bonnes pratiques que l'on
a pu voir durant ce premier cours. a pu voir jusque là.
### Exemple d'exécution ### Exemple d'exécution {-}
<div lang="en-US"> <div lang="en-US">
```bash ```bash

View file

@ -4,7 +4,7 @@ Mon premier conteneur
--------------------- ---------------------
Afin de tester la bonne marche de notre installation, lançons notre premier Afin de tester la bonne marche de notre installation, lançons notre premier
conteneur avec la commande\ : conteneur avec la commande:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -13,7 +13,7 @@ docker container run hello-world
</div> </div>
Cette commande va automatiquement exécuter une série d'actions pour nous, Cette commande va automatiquement exécuter une série d'actions pour nous,
comme indiqué dans le message affiché en retour : comme indiqué dans le message affiché en retour:
D'abord, le daemon va rechercher s'il possède localement l'image D'abord, le daemon va rechercher s'il possède localement l'image
*hello-world*. Si ce n'est pas le cas, il va aller récupérer les différentes *hello-world*. Si ce n'est pas le cas, il va aller récupérer les différentes
@ -23,7 +23,7 @@ conteneur. Enfin, il lance la commande par défaut, telle que définie dans les
métadonnées de l'image. métadonnées de l'image.
Nous pouvons directement utiliser le client pour rechercher une image sur le Nous pouvons directement utiliser le client pour rechercher une image sur le
registre, en utilisant la commande `search` : registre, en utilisant la commande `search`:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -32,7 +32,7 @@ docker search mariadb
</div> </div>
Il est possible de mettre à jour les images locales, ou télécharger les couches Il est possible de mettre à jour les images locales, ou télécharger les couches
d'images qui nous intéressent, en utilisant la commande `pull` : d'images qui nous intéressent, en utilisant la commande `pull`:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -41,40 +41,42 @@ docker image pull ubuntu
</div> </div>
#### Attention {-} ::::: {.warning}
Les registres publics tels quel le Docker Hub mettent à disposition des images Les registres publics tels quel le Docker Hub mettent à disposition des images
officielles, mais aussi des images créés par la communauté. Chaque utilisateur officielles, mais aussi des images créées par la communauté. Chaque utilisateur
est libre d'envoyer une image qu'il a lui-même créée : soit car l'éditeur ne est libre d'envoyer une image qu'il a lui-même créé: soit car l'éditeur ne
proposait pas d'image et que quelqu'un s'est dévoué pour la faire, soit parce proposait pas d'image et que quelqu'un s'est dévoué pour la faire, soit parce
qu'il avait des besoins plus spécifiques qui n'étaient pas couvert par l'image qu'il avait des besoins plus spécifiques qui n'étaient pas couvert par l'image
originale. Il est important de garder en tête que vous téléchargez des originale. Il est important de garder en tête que vous téléchargez des
exécutables, et bien qu'ils s'exécutent dans un environnement isolé, ils exécutables, et bien qu'ils s'exécutent dans un environnement isolé, ils
peuvent contenir du code malveillant. **De la même manière que vous devez être peuvent contenir du code malveillant.
attentif aux binaires que vous exécutez sur votre machine et au contexte de
leurs téléchargements, ici assurez-vous d'avoir confiance dans la personne
affiliée à l'image.**
**De la même manière que vous devez être attentif aux binaires que vous
exécutez sur votre machine et au contexte de leurs téléchargements, ici
assurez-vous d'avoir confiance dans la personne affiliée à l'image.**
:::::
### Arguments de la ligne de commande ### Arguments de la ligne de commande
Remarquez comment on interagit avec chaque *objet Docker* : dans la ligne de Remarquez comment on interagit avec chaque *objet Docker*: dans la ligne de
commande, le premier mot clef est le type d'objet (`container`, `image`, commande, le premier mot clef est le type d'objet (`container`, `image`,
`service`, `network`, `volume`, ...) ; ensuite, vient l'action que l'on `service`, `network`, `volume`, ...) ; ensuite, vient l'action que l'on
souhaite faire dans ce cadre.[^oldcall] souhaite faire dans ce cadre.[^oldcall]
[^oldcall]: cela n'a pas toujours été aussi simple, cette syntaxe n'existe que [^oldcall]: cela n'a pas toujours été aussi simple, cette syntaxe n'existe que
depuis la version 1.13 (janvier 2017). C'est pourquoi, lorsque vous ferez depuis la version 1.13 (janvier 2017). C'est pourquoi, lorsque vous ferez
des recherches sur internet, vous trouverez de nombreux articles utilisant des recherches sur internet, vous trouverez de nombreux articles utilisant
l'ancienne syntaxe, sans le type d'objets : `docker images` au lieu de l'ancienne syntaxe, sans le type d'objets: `docker images` au lieu de
`docker image ls`, `docker run` au lieu de `docker container run`, ... `docker image ls`, `docker run` au lieu de `docker container run`, ...
L'ancienne syntaxe est dépréciée, mais il reste actuellement possible de L'ancienne syntaxe est dépréciée, mais il reste actuellement possible de
l'utiliser. l'utiliser.
Par exemple, pour consulter la liste des images dont nous disposons localement Par exemple, pour consulter la liste des images dont nous disposons localement
(soit parce qu'on les a téléchargées, soit parce que nous les avons créées (soit parce qu'on les a téléchargées, soit parce que nous les avons créées
nous-même), on utilise la commande `ls` sous le type d'objets `image` : nous-même), on utilise la commande `ls` sous le type d'objets `image`:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -85,24 +87,26 @@ docker image ls
### *Image ID*, nom, tag ### *Image ID*, nom, tag
Chaque image est identifiable par son *Image ID* : il s'agit d'un long Chaque image est identifiable par son *Image ID*: il s'agit d'un long
identifiant unique. Chaque modification qui est apportée à l'image identifiant unique. Chaque modification qui est apportée à l'image
générera un *Image ID* différent. Un peu comme un identifiant de générera un *Image ID* différent. Un peu comme un identifiant de
commit dans Git. commit dans Git.
Pour s'y retrouver, on utilise habituellement les noms des images : Pour s'y retrouver, on utilise habituellement les noms des images:
`hello-world` est ainsi le nom de l'image `hello-world` est ainsi le nom de l'image
`1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792`. `1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792`.
Lorsque, comme dans le cas d'Ubuntu, il y a plusieurs *versions* Lorsque, comme dans le cas d'Ubuntu, il y a plusieurs *versions* disponibles,
disponibles, il est possible de préciser la version au moyen d'un il est possible de préciser la version au moyen d'un *tag*. En consultant la
*tag*. En consultant [la documentation[^hubDocUbuntu] qui accompagne chaque conteneur, nous pouvons
documentation](https://hub.docker.com/_/ubuntu) qui accompagne chaque constater la présence de plusieurs versions d'Ubuntu: `trusty`, `xenial`,
conteneur, nous pouvons constater la présence de plusieurs versions `focal` ou `bionic`.
d'Ubuntu : `trusty`, `xenial`, `focal` ou `bionic`.
[^hubDocUbuntu]: Pour voir la documentation des images d'Ubuntu, consultez
<https://hub.docker.com/_/ubuntu>
Par convention, lorsque l'on souhaite désigner un tag en particulier, Par convention, lorsque l'on souhaite désigner un tag en particulier,
on utilise la syntaxe suivante : on utilise la syntaxe suivante:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -110,7 +114,7 @@ ubuntu:focal
``` ```
</div> </div>
Par exemple, pour lancer un conteneur Ubuntu Focal, on utilisera : Par exemple, pour lancer un conteneur Ubuntu Focal, on utilisera:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -119,7 +123,7 @@ docker container run ubuntu:focal
</div> </div>
Chaque nom d'image possède au moins un tag associé par défaut : *latest*. C'est Chaque nom d'image possède au moins un tag associé par défaut: *latest*. C'est
le tag qui est automatiquement recherché lorsque l'on ne le précise pas en le tag qui est automatiquement recherché lorsque l'on ne le précise pas en
lançant l'image. lançant l'image.
@ -127,11 +131,11 @@ lançant l'image.
### Exécuter un programme dans un conteneur ### Exécuter un programme dans un conteneur
Maintenant que nous avons à notre disposition l'image d'un conteneur Ubuntu, Maintenant que nous avons à notre disposition l'image d'un conteneur Ubuntu,
nous allons pouvoir jouer avec ! nous allons pouvoir jouer avec!
La commande `run` de Docker prend comme derniers arguments le programme à La commande `run` de Docker prend comme derniers arguments le programme à
lancer dans le conteneur ainsi que ses éventuels arguments. Essayons d'afficher lancer dans le conteneur ainsi que ses éventuels arguments. Essayons d'afficher
un Hello World : un Hello World:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -146,7 +150,7 @@ transféré dans le conteneur.
Pour nous en convaincre, nous pouvons tenter d'exécuter un programme qui n'est Pour nous en convaincre, nous pouvons tenter d'exécuter un programme qui n'est
pas présent sur notre machine, mais bien uniquement dans le conteneur. Si vous pas présent sur notre machine, mais bien uniquement dans le conteneur. Si vous
n'utilisez pas [Alpine Linux](https://www.alpinelinux.org), vous pourriez n'utilisez pas [Alpine Linux](https://www.alpinelinux.org), vous pourriez
tenter d'utiliser son gestionnaire de paquet `apk`, via : tenter d'utiliser son gestionnaire de paquet `apk`, via:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -184,7 +188,7 @@ programme à exécuter par défaut si l'on ne le précise pas dans la ligne de
commande. commande.
C'est grâce à cela que vous n'avez pas eu besoin de préciser de programme C'est grâce à cela que vous n'avez pas eu besoin de préciser de programme
lorsque vous avez lancé l'image `hello-world` : lorsque vous avez lancé l'image `hello-world`:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -193,7 +197,7 @@ docker container run hello-world
</div> </div>
Il est commun que le programme le plus attendu/approprié soit lancé par défaut, Il est commun que le programme le plus attendu/approprié soit lancé par défaut,
il est donc tout naturel que pour l'image `hello-world`, ce soit `/hello` : il est donc tout naturel que pour l'image `hello-world`, ce soit `/hello`:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -201,20 +205,21 @@ docker container run hello-world /hello
``` ```
</div> </div>
L'image ne contenant que ce programme, vous ne pourrez pas y lancer de shell : L'image ne contenant que ce programme, vous ne pourrez pas y lancer de shell:
<div lang="en-US"> <div lang="en-US">
```bash ```
42sh$ docker container run hello-world /bin/sh 42sh$ docker container run hello-world /bin/sh
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: docker: Error response from daemon: OCI runtime create failed:
starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory": unknown. container_linux.go:349: starting container process caused
"exec: \"/bin/sh\": stat /bin/sh: no such file or directory"
``` ```
</div> </div>
Pour les images `alpine` et `ubuntu`, le programme par défaut est un shell Pour les images `alpine` et `ubuntu`, le programme par défaut est un shell
(`/bin/ash` pour `alpine` et `/bin/bash` pour `ubuntu`), mais il y a une (`/bin/ash` pour `alpine` et `/bin/bash` pour `ubuntu`), mais il y a une
subtilité : il faut ajouter les options `--interactive` et `--tty` pour ne pas subtilité: il faut ajouter les options `--interactive` et `--tty` pour ne pas
que `docker` nous rende la main tout de suite : que `docker` nous rende la main tout de suite:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -239,7 +244,7 @@ s'assure que l'entrée standard ne sera pas fermée (`close(2)`). Nous demandons
interractif[^bashnointer]. interractif[^bashnointer].
[^bashnointer]: Mais il sera possible de l'utiliser sans allouer de TTY, comme [^bashnointer]: Mais il sera possible de l'utiliser sans allouer de TTY, comme
dans cet exemple : dans cet exemple:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -253,7 +258,7 @@ interractif[^bashnointer].
L'option `-i` reste néanmoins nécessaire pour que l'entrée standard soit L'option `-i` reste néanmoins nécessaire pour que l'entrée standard soit
transmise au conteneur. transmise au conteneur.
Rassurez-vous, on peut les abbréger en `-i` et `-t` : Rassurez-vous, on peut les abréger en `-i` et `-t`:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -265,22 +270,22 @@ Rassurez-vous, on peut les abbréger en `-i` et `-t` :
### Les paramètres ### Les paramètres
Vous avez remarqué le placement des options `--tty` et `--interactive` ? Avant Vous avez remarqué le placement des options `--tty` et `--interactive`? Avant
le nom de l'image, elles sont utilisées par Docker pour modifier le comportement le nom de l'image, elles sont utilisées par Docker pour modifier le comportement
du `run`. En fait, tout comme `git(1)` et ses sous-commandes, chaque niveau de du `run`. En fait, tout comme `git(1)` et ses sous-commandes, chaque niveau de
commande peut prendre des paramètres : commande peut prendre des paramètres:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
docker DOCKER_PARAMS container run RUN_OPTS image IMAGE_CMD IMAGE_ARGS ... docker DOCKER_PARAMS container run RUN_OPTS image IMAGE_CMD IMAGE_ARGS …
``` ```
</div> </div>
Par exemple : Par exemple:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
docker -H unix:///var/run/docker.sock container run -it alpine /bin/ash -c "echo foo" docker -H unix:///run/docker.sock container run -it alpine /bin/ash -c "echo foo"
``` ```
</div> </div>
@ -295,13 +300,13 @@ conteneur.
Avant de quitter notre conteneur, regardons, à l'aide d'un autre terminal, Avant de quitter notre conteneur, regardons, à l'aide d'un autre terminal,
l'état de notre conteneur. La commande suivante permet d'obtenir la liste des l'état de notre conteneur. La commande suivante permet d'obtenir la liste des
conteneurs en cours d'exécution : conteneurs en cours d'exécution:
<div lang="en-US"> <div lang="en-US">
``` ```
42sh$ docker container ls 42sh$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4c39fc049cd1 ubuntu "/bin/bash" 6 minutes ago Up 5 minutes suspicious_galileo 4c39fc049cd1 ubuntu "/bin/bash" 6 minutes ago Up 5 minutes bold_gates
``` ```
</div> </div>

View file

@ -1,24 +1,16 @@
\newpage
Installation Installation
------------ ------------
Avant de voir de quoi il s'agit, afin de gagner du temps, nous allons commencer Docker repose sur plusieurs techniques implémentées dans les noyaux Linux
par installer Docker. récents (et plus marginalement, Windows). Ces techniques, contrairement aux
instructions de virtualisation qui rendent les hyperviseurs attractifs, ne sont
### Prérequis pas limitées à une architecture de microprocesseur spécifique ; cependant la
communauté autour de Docker utilise principalement l'architecture `amd64`,
Docker repose sur plusieurs techniques implémentées dans les récents noyaux c'est sur cette dernière que Docker pourra être exploité à son plein potentiel,
Linux (et plus marginalement, Windows). Nous consacrerons les prochains cours à suivi de près par l'architecture `arm64`.
comprendre leur fonctionnement. Ces techniques, contrairement aux instructions
de virtualisation qui rendent les hyperviseurs attractifs, ne sont pas limitées
à une architecture de microprocesseur spécifique ; cependant la communauté
autour de Docker utilise principalement l'architecture `amd64`, c'est sur cette
dernière que Docker pourra être exploité à son plein potentiel, suivi de près
par l'architecture `arm64`.
Avant de continuer, assurez-vous que votre machine a bien démarré sur un noyau Avant de continuer, assurez-vous que votre machine a bien démarré sur un noyau
64 bits. Le retour de la commande `uname -m` doit vous indiquer : 64 bits. Le retour de la commande `uname -m` doit vous indiquer:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -26,7 +18,7 @@ x86_64
``` ```
</div> </div>
Ou si vous êtes intrépide : Ou si vous êtes intrépide:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -34,7 +26,7 @@ aarch64
``` ```
</div> </div>
Assurez-vous également d'avoir un noyau récent, avec la commande `uname -r` : Assurez-vous également d'avoir un noyau récent, avec la commande `uname -r`:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -46,53 +38,66 @@ Rassurez-vous, même si vous n'avez pas compilé le dernier noyau disponible sur
[`kernel.org`](https://www.kernel.org/), Docker s'utilise à partir de Linux 3.10. [`kernel.org`](https://www.kernel.org/), Docker s'utilise à partir de Linux 3.10.
### Par le gestionnaire de paquets ### Sous Linux, par le gestionnaire de paquets
En général, votre distribution mettra à votre disposition une version de Docker En général, votre distribution mettra à votre disposition une version de Docker
plus ou moins récente. Sous Debian et ses dérivés (Ubuntu, Mint, ...) le paquet plus ou moins récente. Sous Debian et ses dérivés (Ubuntu, Mint, ...) le paquet
a été nommé [`docker.io`](https://packages.debian.org/sid/docker.io). a été nommé [`docker.io`](https://packages.debian.org/sid/docker.io).
Si dans un environnement de production, on préférera sans doute utiliser une Si dans un environnement de production, on préférera sans doute utiliser une
version déjà bien éprouvée (comme celle des dépôts de sa distribution), pour ce version déjà bien éprouvée (comme celle des dépôts de sa distribution), pour
cours, nous allons avoir besoin de la **dernière version bien suivre les exemples, nous allons avoir besoin de la **dernière version
disponible**. Référez-vous à la documentation officielle correspondant à votre disponible**. Référez-vous à la documentation officielle correspondant à votre
distribution : distribution:
<https://docs.docker.com/engine/install/debian/> <https://docs.docker.com/engine/install/debian/>
**Et Kali Linux alors ?** Kali étant basée sur Debian, référez-vous à ::::: {.question}
**Et Kali Linux alors?** Kali étant basée sur Debian, référez-vous à
la procédure d'installation de cette distribution. la procédure d'installation de cette distribution.
:::::
### Windows et macOS ### Sous Windows et macOS
Bien que les fonctionnalités de contenerisation de Docker que nous utiliserons Bien que les fonctionnalités de contenerisation de Docker que nous utiliserons
ne soient disponibles que sous Linux, il est possible d'utiliser Docker de ne soient disponibles que sous Linux, il est possible d'utiliser Docker de
manière déportée : le daemon Docker tournera dans une VM Linux, mais vous manière déportée: le daemon Docker tournera dans une machine virtuelle Linux,
pourrez interagir avec lui via votre ligne de commande habituelle. mais vous pourrez interagir avec lui via votre ligne de commande habituelle.
Téléchargez la version correspondante à votre système d'exploitation : Téléchargez la version correspondant à votre système d'exploitation:
* [Docker Desktop for Mac](https://hub.docker.com/editions/community/docker-ce-desktop-mac) * Docker Desktop for Mac:\
* [Docker Desktop for Windows](https://hub.docker.com/editions/community/docker-ce-desktop-windows) <https://hub.docker.com/editions/community/docker-ce-desktop-mac>
Une fois l'installation terminée, lancez l'application : elle ajoutera une * Docker Desktop for Windows:\
<https://hub.docker.com/editions/community/docker-ce-desktop-windows>
Une fois l'installation terminée, lancez l'application: elle ajoutera une
icône dans la zone de notification, vous permettant de contrôler l'exécution de icône dans la zone de notification, vous permettant de contrôler l'exécution de
la machine virtuelle sous-jacente. la machine virtuelle sous-jacente.
Notez que depuis septembre 2021, ces applications passent sous une licence ::::: {.warning}
payante pour les grosses entreprises[^DockerSubscription]. Cela ne nous
concerne pas, car la licence est gratuite pour un usage éducatif ou Depuis septembre 2021, ces applications passent sous une licence payante pour
personnel. Notez que ce n'est pas le binaire Docker qui change de licence, elle les grosses entreprises[^DockerSubscription]. Cela ne nous concerne pas, car la
reste libre, mais seulement les applications Docker Desktop. 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.
:::::
[^DockerSubscription]: <https://www.docker.com/blog/updating-product-subscriptions/> [^DockerSubscription]: <https://www.docker.com/blog/updating-product-subscriptions/>
### Évaluation en ligne ### Évaluation en ligne
Si vous rencontrez des difficultés pour vous lancer, le projet Si vous rencontrez des difficultés pour vous lancer, le projet Play With
[Play With Docker](https://labs.play-with-docker.com/) vous donne accès à Docker[^PlayWithDocker] vous donne accès à un bac à sable
un bac à sable dans lequel vous pourrez commencer à faire ce TP. dans lequel vous pourrez commencer à faire les exercices à suivre.
[^PlayWithDocker]: Play With Docker est accessible à cette addresse: <https://labs.play-with-docker.com/>
Il vous faudra disposer [d'un compte Il vous faudra disposer [d'un compte
Docker](https://hub.docker.com/signup). Une fois identifié, vous pourrez créer Docker](https://hub.docker.com/signup). Une fois identifié, vous pourrez créer
@ -101,7 +106,7 @@ une nouvelle instance, et vous connecter dessus via SSH.
### Vérifier la bonne marche de l'installation ### Vérifier la bonne marche de l'installation
Vous devriez maintenant être capable de lancer la commande suivante : Vous devriez maintenant être capable de lancer la commande suivante:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -109,7 +114,7 @@ docker version
``` ```
</div> </div>
Une sortie similaire au bloc suivant devrait apparaître sur votre écran : Une sortie similaire au bloc suivant devrait apparaître sur votre écran:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -149,8 +154,8 @@ Server:
#### `no such file or directory`? #### `no such file or directory`?
Si vous avez cette erreur : `dial unix /var/run/docker.sock: no such file or 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 deamon n'est sans doute pas lancé. Lancez-le:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -161,9 +166,9 @@ sudo service docker restart
#### `permission denied`? #### `permission denied`?
Si vous avez cette erreur : `dial unix /var/run/docker.sock: permission Si vous avez cette erreur: `dial unix /var/run/docker.sock: permission
denied.`, ajoutez votre utilisateur au groupe `docker` et **relancez votre denied.`, ajoutez votre utilisateur au groupe `docker` et **relancez votre
session** : session**:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -171,5 +176,10 @@ sudo gpasswd -a $USER docker
``` ```
</div> </div>
**Attention :** cette action n'est pas anodine d'un point de vue sécurité : ::::: {.warning}
Cette action n'est pas anodine d'un point de vue de la sécurité:
<https://docs.docker.com/engine/security/#docker-daemon-attack-surface> <https://docs.docker.com/engine/security/#docker-daemon-attack-surface>
:::::

View file

@ -0,0 +1,44 @@
## Exercice {-}
À vous maintenant de connecter une instance de `nemunaire/fic-admin` à sa base
de données.
Ne vous embêtez pas avec les mots de passes des services, initialisez la base
de données avec le nom d'utilisateur et le mot de passe par défaut. Vous les
obtiendrez en lisant la documentation de l'image fic-admin:
<https://hub.docker.com/r/nemunaire/fic-admin/>
<div lang="en-US">
```bash
docker run --rm -e MYSQL_HOST=mysql_cntr_name nemunaire/fic-admin -help
```
</div>
Notez la définition de la variable d'environnement `MYSQL_HOST`, celle-ci
indique le nom du serveur vers lequel le service doit se connecter.
Vous aurez besoin de créer:
- un volume pour stocker la base de données,
- un réseau, dans lequel vous connecterez la base de données et le conteneur applicatif.
Une fois le service `fic-admin` lancé, vous pouvez exposer le port 8081, sur
lequel vous devriez voir l'interface d'admin: <http://localhost:8081/>.
Placez les différentes commandes (volumes, réseau, `run`, ...) dans un
script `ficadmin-run.sh`. Vous devriez pouvoir appeler ce script
plusieurs fois, sans que les données ne soient perdues, entre deux
arrêts.
### Exemple d'exécution
<div lang="en-US">
```bash
42sh$ ./ficadmin-run.sh
http://localhost:12345/
42sh$ #docker kill db ficadmin
42sh$ ./ficadmin-run.sh # le script relancera une base de données,
# sans avoir perdu les données
http://localhost:12345/
```
</div>

View file

@ -0,0 +1,34 @@
### 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'initialisé le volume attaché à `/var/lib/mysql`. Les
démarrage 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ées.
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
correctement l'exécution d'un conteneur.
En réalisant l'exercice, vous serez sans doute confronté à des comportements
étranges, que vous ne pourriez comprendre qu'en ayant la main sur le conteneur,
via un shell.
Lorsqu'un conteneur est actif, vous pouvez y lancer un nouveau processus,
notamment un shell par exemple.
<div lang="en-US">
```bash
docker container exec -it mycloud /bin/bash
(inctnr)$ ping mysql_cntr_name
```
</div>
Notez qu'il n'est pas possible d'`exec` dans un conteneur éteint, et que si la
commande initiale du conteneur se termine, tous les `exec` seront instantanément
tués.

View file

@ -12,14 +12,14 @@ ses données, mais la plupart des applications réclament un serveur de base de
données. données.
Les bonnes pratiques nous dictent de ne pas placer plus d'un service par Les bonnes pratiques nous dictent de ne pas placer plus d'un service par
conteneur : en effet, on peut vouloir mettre à jour l'applicatif sans pour conteneur: en effet, on peut vouloir mettre à jour l'applicatif sans pour
autant redémarrer sa base de données, etc. Nous allons donc voir dans cette autant redémarrer sa base de données, etc. Nous allons donc voir dans cette
partie comment lier deux conteneurs. partie comment lier deux conteneurs.
## Mise en place du webservice ## Mise en place du webservice
Nous allons utiliser l'interface d'administration des serveurs du FIC : Nous allons utiliser l'interface d'administration des serveurs du FIC:
[`nemunaire/fic-admin`](https://hub.docker.com/r/nemunaire/fic-admin). [`nemunaire/fic-admin`](https://hub.docker.com/r/nemunaire/fic-admin).
En lançant le conteneur avec les mêmes options que `youp0m`, les journaux En lançant le conteneur avec les mêmes options que `youp0m`, les journaux
@ -30,17 +30,17 @@ MariaDB](https://hub.docker.com/_/mariadb).
## Les pilotes réseau ## Les pilotes réseau
Docker propose de base trois pilotes (*drivers*) pour « gérer » cela : Docker propose de base trois pilotes (*drivers*) pour « gérer » cela:
- `none` : pour limiter les interfaces réseau du conteneur à l'interface de - `none`: pour limiter les interfaces réseau du conteneur à l'interface de
loopback `lo` ; loopback `lo` ;
- `host` : pour partager la pile réseau avec l'hôte ; - `host`: pour partager la pile réseau avec l'hôte ;
- `bridge` : pour créer une nouvelle pile réseau par conteneur et rejoindre un - `bridge`: pour créer une nouvelle pile réseau par conteneur et rejoindre un
pont réseau dédié. pont réseau dédié.
Ces trois *drivers* sont instanciés de base dans Docker avec le même nom que Ces trois *drivers* sont instanciés de base dans Docker avec le même nom que
leur pilote. Pour consulter la liste de réseaux utilisables, lancez : leur pilote. Pour consulter la liste de réseaux utilisables, lancez:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -52,7 +52,7 @@ d5d907add6e2 host host local
``` ```
</div> </div>
Par défaut, c'est le réseau `bridge` (de type `bridge`) qui est employé : ce Par défaut, c'est le réseau `bridge` (de type `bridge`) qui est employé: ce
réseau utilise le pont `docker0` que vous pouvez voir dans vos interfaces réseau utilise le pont `docker0` que vous pouvez voir dans vos interfaces
réseau via `ip link`. C'est via ce pont que les conteneurs peuvent avoir accès réseau via `ip link`. C'est via ce pont que les conteneurs peuvent avoir accès
à Internet, au travers d'une couche de NAT. à Internet, au travers d'une couche de NAT.
@ -76,7 +76,7 @@ Afin de contrôler quels échanges peuvent être réalisés entre les conteneurs
est recommandé de créer des réseaux utilisateur. est recommandé de créer des réseaux utilisateur.
La création d'un réseau se fait tout simplement au travers des sous-commandes La création d'un réseau se fait tout simplement au travers des sous-commandes
relatives aux objets Docker `network` : relatives aux objets Docker `network`:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -86,7 +86,7 @@ docker network create --driver bridge my_fic
C'est ensuite ce nom de réseau que vous passerez à l'option `--network` de vos C'est ensuite ce nom de réseau que vous passerez à l'option `--network` de vos
`run`, ou vous pouvez également faire rejoindre un conteneur déjà lancé à un `run`, ou vous pouvez également faire rejoindre un conteneur déjà lancé à un
réseau : réseau:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -97,84 +97,3 @@ docker network connect NETWORK CONTAINER
Lorsque plusieurs conteneurs ont rejoint un réseau utilisateur, ils peuvent Lorsque plusieurs conteneurs ont rejoint un réseau utilisateur, ils peuvent
mutuellement se découvrir grâce à un système de résolution de nom basé sur leur mutuellement se découvrir grâce à un système de résolution de nom basé sur leur
nom de conteneur. nom de conteneur.
## Exercice {-}
À vous maintenant de connecter une instance de `nemunaire/fic-admin` à sa base
de données.
Ne vous embêtez pas avec les mots de passes des services, initialisez la base
de données avec le nom d'utilisateur et le mot de passe par défaut. Vous les
obtiendrez en lisant la [documentation de l'image
fic-admin](https://hub.docker.com/r/nemunaire/fic-admin/) :
<div lang="en-US">
```bash
docker container run --rm -e MYSQL_HOST=mysql_cntr_name nemunaire/fic-admin -help
```
</div>
Notez la définition de la variable d'environnement `MYSQL_HOST`, celle-ci
indique le nom du serveur vers lequel le service doit se connecter.
Vous aurez besoin de créer un volume pour stocker la base de données, un réseau
dans lequel vous connecterez la base de données et le conteneur applicatif.
Une fois le service `fic-admin` lancé, vous pouvez exposer le port 8081, sur
lequel vous devriez voir l'interface d'admin : <http://localhost:8081/>.
Placez les différentes commandes (volumes, réseau, `run`, ...) dans un
script `ficadmin-run.sh`, que vous rendrez à la fin du TP. Vous
devriez pouvoir appeler ce script plusieurs fois, sans que les données
ne soient perdues, entre deux arrêts.
### Exemple d'exécution
<div lang="en-US">
```bash
42sh$ ./ficadmin-run.sh
http://localhost:12345/
42sh$ #docker kill db ficadmin
42sh$ ./ficadmin-run.sh # le script relancera une base de données,
# sans avoir perdu les données
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'initialisé le volume attaché à `/var/lib/mysql`. Les
démarrage 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ées.
Si vous rencontrez des difficultés pour connecter votre conteneur `fic-admin` à
`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
correctement l'exécution d'un conteneur.
En réalisant l'exercice, vous serez sans doute confronté à des comportements
étranges, que vous ne pourriez comprendre qu'en ayant la main sur le conteneur,
via un shell.
Lorsqu'un conteneur est actif, vous pouvez y lancer un nouveau processus,
notamment un shell par exemple.
<div lang="en-US">
```bash
docker container exec -it ficadmin /bin/bash
(inctnr)$ ping mysql_cntr_name
```
</div>
Notez qu'il n'est pas possible d'`exec` dans un conteneur éteint, et que si la
commande initiale du conteneur se termine, tous les `exec` seront également
tués.

View file

@ -17,7 +17,7 @@ pour se rendre sur la page de connexion. Une autre machine de votre réseau
local devrait également pouvoir accéder à la plate-forme, simplement en local devrait également pouvoir accéder à la plate-forme, simplement en
renseignant l'IP de votre machine et en ajoutant éventuellement des règles de renseignant l'IP de votre machine et en ajoutant éventuellement des règles de
pare-feu (mais cette dernière partie n'est pas demandée, gardez simplement en 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 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). machine sans pare-feu configurée, cela ne demande pas d'étape supplémentaire).
Votre script devra se limiter aux notions vues durant ce TP (ie. sans utiliser Votre script devra se limiter aux notions vues durant ce TP (ie. sans utiliser
@ -67,7 +67,7 @@ Par ailleurs, n'oubliez pas de répondre à
## Tarball ## Tarball
Tous les fichiers identifiés comme étant à rendre pour ce TP sont à Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...). placer dans une tarball (pas d'archive ZIP, RAR, ...).
Voici une arborescence type: Voici une arborescence type:
@ -80,7 +80,7 @@ login_x-TP1/mycloud-run.sh
## Signature du rendu ## Signature du rendu
Deux méthodes sont utilisables pour signer votre rendu : Deux méthodes sont utilisables pour signer votre rendu:
* signature du courriel ; * signature du courriel ;
* signature de la tarball. * signature de la tarball.
@ -106,7 +106,7 @@ signature.
#### No public key #### No public key
Si vous recevez un rapport avec l'erreur suivante : Si vous recevez un rapport avec l'erreur suivante:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -129,7 +129,7 @@ rendu.
#### Not explicit username #### Not explicit username
Si vous recevez un rapport avec l'erreur suivante : Si vous recevez un rapport avec l'erreur suivante:
<div lang="en-US"> <div lang="en-US">
``` ```
@ -144,7 +144,7 @@ données.
#### I've decided to skip your e-mail #### I've decided to skip your e-mail
Si vous recevez un rapport concluant ainsi : Si vous recevez un rapport concluant ainsi:
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -3,7 +3,7 @@
Stockage de données applicatives Stockage de données applicatives
================================ ================================
Le concept principal de Docker est de concevoir des conteneurs applicatifs : on Le concept principal de Docker est de concevoir des conteneurs applicatifs: on
va préférer assigner un unique rôle à un conteneur (donc généralement on ne va va préférer assigner un unique rôle à un conteneur (donc généralement on ne va
lancer qu'une seule application par conteneur) et concevoir un service complet lancer qu'une seule application par conteneur) et concevoir un service complet
en créant un groupe de conteneurs, partageant des données entre eux par des en créant un groupe de conteneurs, partageant des données entre eux par des
@ -25,21 +25,21 @@ Il est possible de monter un répertoire de la machine hôte dans un
conteneur. L'intérêt reste plutôt limité à des fins de facilité ou de test, par conteneur. L'intérêt reste plutôt limité à des fins de facilité ou de test, par
exemple si vous voulez partager des fichiers avec votre voisin, en passant par exemple si vous voulez partager des fichiers avec votre voisin, en passant par
le protocole HTTP, mais sans se casser la tête à installer et configurer un le protocole HTTP, mais sans se casser la tête à installer et configurer un
serveur web : serveur web:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
docker container run --rm -p 80:80 -v ~/Downloads:/usr/share/nginx/html:ro -d nginx docker run --rm -p 80:80 -v ~/Downloads:/usr/share/nginx/html:ro -d nginx
``` ```
</div> </div>
Une fois cette commande lancée, votre voisin pourra accéder à votre dossier Une fois cette commande lancée, votre voisin pourra accéder à votre dossier
Downloads en renseignant l'IP de votre machine dans son navigateur favori ! Downloads en renseignant l'IP de votre machine dans son navigateur favori!
Par défaut, `nginx` ne va pas permettre de lister le contenu du répertoire (et Par défaut, `nginx` ne va pas permettre de lister le contenu du répertoire (et
va afficher une page 404, car il cherche un fichier `index.html` dans votre va afficher une page 404, car il cherche un fichier `index.html` dans votre
répertoire). Vous pouvez par contre accéder à un fichier directement, par répertoire). Vous pouvez par contre accéder à un fichier directement, par
exemple : <http://10.42.12.23/dQw4w9WgXcQ.mp4> exemple: <http://10.42.12.23/dQw4w9WgXcQ.mp4>
## Les volumes ## Les volumes
@ -50,7 +50,7 @@ soucier de leur réel emplacement.
Comme il s'agit d'un objet, la première chose à faire va être de créer notre Comme il s'agit d'un objet, la première chose à faire va être de créer notre
volume : volume:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -59,7 +59,7 @@ docker volume create prod_foodp0m
``` ```
</div> </div>
Ensuite, nous pouvons démarrer un conteneur utilisant, par exemple : Ensuite, nous pouvons démarrer un conteneur utilisant, par exemple:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -67,7 +67,7 @@ docker container run --mount source=prod_youp0m,target=/images nemunaire/youp0m
``` ```
</div> </div>
On pourra également faire de même avec un conteneur MySQL : On pourra également faire de même avec un conteneur MySQL:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -86,7 +86,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 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 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 points de montages utilisant le système de fichiers `tmpfs` et donc résidant
exclusivement en RAM\ : exclusivement en RAM\:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -106,12 +106,15 @@ pour mettre à jour ou relancer un conteneur, sans perdre les données. Un autre
intérêt est de pouvoir partager des fichiers entre plusieurs conteneurs. intérêt est de pouvoir partager des fichiers entre plusieurs conteneurs.
Il est ainsi parfaitement possible de lancer deux conteneurs qui partagent le Il est ainsi parfaitement possible de lancer deux conteneurs qui partagent le
même volume : même volume:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
docker container run -d --mount source=prod_youp0m,target=/images -p 8080:8080 nemunaire/youp0m docker container run -d --mount source=prod_youp0m,target=/images \
docker container run -d --mount source=prod_youp0m,target=/images -p 8081:8080 nemunaire/youp0m -p 8080:8080 nemunaire/youp0m
docker container run -d --mount source=prod_youp0m,target=/images \
-p 8081:8080 nemunaire/youp0m
``` ```
</div> </div>
@ -119,7 +122,7 @@ Dans cet exemple, l'ajout d'une image dans un conteneur l'ajoutera également
dans le second. dans le second.
Un exemple plus intéressant serait sur une architecture de micro-services Un exemple plus intéressant serait sur une architecture de micro-services
traitant des fichiers de grande taille : plutôt que de faire passer les traitant des fichiers de grande taille: plutôt que de faire passer les
fichiers par un système de message/socket, on peut partager un volume pour fichiers par un système de message/socket, on peut partager un volume pour
épargner les coûts de transferts inutiles, lorsqu'ils ne changent pas de épargner les coûts de transferts inutiles, lorsqu'ils ne changent pas de
machine. machine.

View file

@ -13,13 +13,13 @@ d'une socket.
Le client peut d'ailleurs ne pas être sur la même machine qui exécutera Le client peut d'ailleurs ne pas être sur la même machine qui exécutera
effectivement les conteneurs.[^dockermachine] 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 *Docker4Windows* ou *Docker4Mac*:
une machine virtuelle Linux est lancée parallèlement au système de base et 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 deamon dans la machine virtuelle.
[^dockermachine]: Il suffit de modifier la variable d'environnement [^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_HOST` ou de passer le paramètre `-H` suivi de l'URL de la socket à
`docker`. Voir aussi : <https://docs.docker.com/machine/overview/> `docker`. Voir aussi: <https://docs.docker.com/machine/overview/>
Commençons par planter le décor, en détaillant les principaux mécanismes de Commençons par planter le décor, en détaillant les principaux mécanismes de
Docker. Docker.
@ -30,17 +30,17 @@ Docker.
Une image Docker est un système de fichiers en lecture seule. Elle est formée 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. d'un ensemble de couches, agrégées selon le principe d'UnionFS.
Une image peut, par exemple, contenir : Une image peut, par exemple, contenir:
* un système Ubuntu opérationnel, * un système Ubuntu opérationnel,
* le programme `busybox`, * le programme `busybox`,
* un serveur web et votre application web, prêts à l'emploi, * un serveur web et votre application web, prêts à l'emploi,
* ... *...
Les images sont utilisées comme **modèle** qui sera ensuite dupliqué à chaque Les images sont utilisées comme **modèle** qui sera ensuite dupliqué à chaque
fois que l'on démarrera un nouveau conteneur. fois que l'on démarrera un nouveau conteneur.
Il y a deux méthodes pour obtenir des images Docker : soit les construire avec 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 outils fournis, soit les récupérer depuis un registre.
@ -50,8 +50,8 @@ 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 contenant des images. Ils permettent de récupérer des images, mais également
d'en envoyer. d'en envoyer.
Le registre utilisé de base est le [Docker Hub](https://hub.docker.com/) : il Le registre utilisé de base est le [Docker Hub](https://hub.docker.com/): il
contient à la fois des images officielles (ubuntu, debian, nginx, ...), des contient à la fois des images officielles (ubuntu, debian, nginx, ...), des
images créées par des utilisateurs, mais aussi des images de grands éditeurs, images créées par des utilisateurs, mais aussi des images de grands éditeurs,
payantes, à destination des entreprises. payantes, à destination des entreprises.
@ -65,10 +65,10 @@ proposent également.
### Les conteneurs Docker ### Les conteneurs Docker
Alors que les images constituent la partie immuable de Docker, les conteneurs Alors que les images constituent la partie immuable de Docker, les conteneurs
sont sa partie vivante. Chaque conteneur est créé à partir d'une image : à 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 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 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. 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% } ![Couches d'un conteneur](layers-multi-container.png "Couches d'un conteneur"){ width=70% }

View file

@ -113,10 +113,13 @@ Puis on lui demande la génération d'un rapport `html` :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
paclair --conf conf.yml Docker nemunaire/fic-admin analyse --output-format html --output-report file paclair --conf conf.yml Docker nemunaire/fic-admin analyse \
--output-format html --output-report file
``` ```
</div> </div>
![Rapport d'analyse statique des vulnérabilités par Clair](paclair.png)
Si l'on souhaite uniquement avoir des statistiques dans la console : Si l'on souhaite uniquement avoir des statistiques dans la console :
<div lang="en-US"> <div lang="en-US">

View file

@ -4,7 +4,7 @@ Si vous n'avez pas déjà le binaire `linuxkit`, vous pouvez télécharger ici 
<https://github.com/linuxkit/linuxkit/releases/latest>. <https://github.com/linuxkit/linuxkit/releases/latest>.
Notez qu'étant donné qu'il est écrit en Go, aucune dépendance n'est nécessaire Notez qu'étant donné qu'il est écrit en Go, aucune dépendance n'est nécessaire
en plus du binaire[^lollibc] ;-) en plus du binaire[^lollibc] ;-)
[^lollibc]: à condition tout de même que vous utilisiez une libc habituelle. [^lollibc]: à condition tout de même que vous utilisiez une libc habituelle.
@ -17,17 +17,17 @@ Le fichier utilisé pour construire notre image se décompose en plusieurs
parties : parties :
- `kernel` : il est attendu ici une image OCI contenant le nécessaire pour - `kernel` : il est attendu ici une image OCI contenant le nécessaire pour
pouvoir utiliser un noyau : l'image du noyau, ses modules et un initramfs ; pouvoir utiliser un noyau : l'image du noyau, ses modules et un initramfs ;
- `init` : l'ensemble des images OCI de cette liste seront fusionnés pour - `init` : l'ensemble des images OCI de cette liste seront fusionnés pour
donner naissance au *rootfs* de la machine. On n'y place normalement qu'un donner naissance au *rootfs* de la machine. On n'y place normalement qu'un
gestionnaire de conteneur, qui sera chargé de lancer chaque conteneur au bon gestionnaire de conteneur, qui sera chargé de lancer chaque conteneur au bon
moment ; moment ;
- `onboot`, `onshutdown` et `services` : il s'agit de conteneurs qui seront - `onboot`, `onshutdown` et `services` : il s'agit de conteneurs qui seront
lancés par le système disponible dans l'`init`, au bon moment. Les conteneurs lancés par le système disponible dans l'`init`, au bon moment. Les conteneurs
indiqués dans `onboot` seront lancés **séquentiellement** au démarrage de la indiqués dans `onboot` seront lancés **séquentiellement** au démarrage de la
machine, ceux dans `onshutdown` seront lancés lors de l'arrêt de la machine, ceux dans `onshutdown` seront lancés lors de l'arrêt de la
machine. Les conteneurs dans `services` seront lancés simultanément une fois machine. Les conteneurs dans `services` seront lancés simultanément une fois
que le dernier conteneur de `onboot` aura rendu la main ; que le dernier conteneur de `onboot` aura rendu la main ;
- `files` : des fichiers supplémentaires à placer dans le rootfs. - `files` : des fichiers supplémentaires à placer dans le rootfs.
Le format est documenté Le format est documenté
@ -63,7 +63,7 @@ trust:
</div> </div>
L'image `getty` est très pratique pour déboguer, car elle permet d'avoir un L'image `getty` est très pratique pour déboguer, car elle permet d'avoir un
shell sur la machine ! shell sur la machine !
On notera cependant que, positionné dans `services`, le shell que nous On notera cependant que, positionné dans `services`, le shell que nous
obtiendrons sera lui-même exécuté dans un conteneur, nous n'aurons donc pas un obtiendrons sera lui-même exécuté dans un conteneur, nous n'aurons donc pas un
@ -143,7 +143,7 @@ réutiliser plus tard ce chemin, en remplacement du mot clef `new` :
Toute la puissance de `linuxkit` repose dans son système de construction et Toute la puissance de `linuxkit` repose dans son système de construction et
surtout de lancement. En effet, il peut construire des images pour un grand surtout de lancement. En effet, il peut construire des images pour un grand
nombre de plate-forme, mais il est également possible d'utiliser les API de ces nombre de plate-forme, mais il est également possible d'utiliser les API de ces
plates-formes pour aller y lancer des instances de cette image ! plates-formes pour aller y lancer des instances de cette image !
Pour construire l'image faite précédemment : Pour construire l'image faite précédemment :
@ -154,7 +154,7 @@ linuxkit build hello.yml
</div> </div>
Cela va générer plusieurs fichiers dont un noyau (extrait de l'image de la Cela va générer plusieurs fichiers dont un noyau (extrait de l'image de la
partie `kernel`) ainsi qu'une image. Exactement ce qu'attend QEMU ! Pour partie `kernel`) ainsi qu'une image. Exactement ce qu'attend QEMU ! Pour
tester, n'attendons pas davantage pour lancer : tester, n'attendons pas davantage pour lancer :
<div lang="en-US"> <div lang="en-US">
@ -227,7 +227,7 @@ choix](https://www.vaultproject.io/docs/configuration/storage/index.html)
Au démarrage, Vault devra déjà être configuré pour parler à sa base de données, Au démarrage, Vault devra déjà être configuré pour parler à sa base de données,
qui devra se trouver dans un conteneur isolé et non accessible d'internet. Il qui devra se trouver dans un conteneur isolé et non accessible d'internet. Il
faudra donc établir un lien `virtual ethernet` entre les deux conteneurs ; et faudra donc établir un lien `virtual ethernet` entre les deux conteneurs ; et
ne pas oublier de le configurer (automatiquement au *runtime*, grâce à un ne pas oublier de le configurer (automatiquement au *runtime*, grâce à un
[`poststart` [`poststart`
*hook*](https://github.com/opencontainers/runtime-spec/blob/master/config.md#posix-platform-hooks) *hook*](https://github.com/opencontainers/runtime-spec/blob/master/config.md#posix-platform-hooks)

View file

@ -8,8 +8,8 @@ tirant parti des conteneurs. Il se positionne comme un système de construction
de machine. En effet, grâce à lui, nous allons pouvoir générer des systèmes de machine. En effet, grâce à lui, nous allons pouvoir générer des systèmes
complets, *bootable* dans QEMU, VirtualBox, VMware ou même sur des machines complets, *bootable* dans QEMU, VirtualBox, VMware ou même sur des machines
physiques, qu'il s'agisse de PC ou bien même de Raspberry Pi, ou même encore physiques, qu'il s'agisse de PC ou bien même de Raspberry Pi, ou même encore
des images pour les différents fournisseurs de cloud ! des images pour les différents fournisseurs de cloud !
Bien entendu, au sein de ce système, tout est fait de conteneur ! Alors quand Bien entendu, au sein de ce système, tout est fait de conteneur ! Alors quand
il s'agit de donner une IP publique utilisable par l'ensemble des conteneurs, il s'agit de donner une IP publique utilisable par l'ensemble des conteneurs,
il faut savoir jouer avec les *namespaces* pour arriver à ses fins ! il faut savoir jouer avec les *namespaces* pour arriver à ses fins !

View file

@ -9,14 +9,14 @@ fragmentation de l'écosystème.
Trois spécifications ont été écrites : Trois spécifications ont été écrites :
- [`runtime-spec`](https://github.com/opencontainers/runtime-spec/blob/master/spec.md#platforms): définit les paramètres du démarrage d'un conteneur ; - [`runtime-spec`](https://github.com/opencontainers/runtime-spec/blob/master/spec.md#platforms): définit les paramètres du démarrage d'un conteneur ;
- [`image-spec`](https://github.com/opencontainers/image-spec/blob/master/spec.md): définit la construction, le transport et la préparation des images ; - [`image-spec`](https://github.com/opencontainers/image-spec/blob/master/spec.md): définit la construction, le transport et la préparation des images ;
- [`distribution-spec`](https://github.com/opencontainers/distribution-spec/blob/master/spec.md): définit la manière dont sont partagées et récupérées les images. - [`distribution-spec`](https://github.com/opencontainers/distribution-spec/blob/master/spec.md): définit la manière dont sont partagées et récupérées les images.
## `runtime-spec` ## `runtime-spec`
`runc` est l'implémentation de cette spécification ; elle a été extraite de `runc` est l'implémentation de cette spécification ; elle a été extraite de
`docker`, puis donnée par Docker Inc. à l'OCI. `docker`, puis donnée par Docker Inc. à l'OCI.
Pour démarrer un conteneur, la spécification indique qu'il est nécessaire Pour démarrer un conteneur, la spécification indique qu'il est nécessaire
@ -82,5 +82,5 @@ effectivement nos conteneurs, c'est que l'on peut changer cette implémentation
? la réponse dans l'article : ? la réponse dans l'article :
<https://ops.tips/blog/run-docker-with-forked-runc/> <https://ops.tips/blog/run-docker-with-forked-runc/>
Et `containerd` dans l'histoire ? Et `containerd` dans l'histoire ?
<https://hackernoon.com/docker-containerd-standalone-runtimes-heres-what-you-should-know-b834ef155426> <https://hackernoon.com/docker-containerd-standalone-runtimes-heres-what-you-should-know-b834ef155426>

View file

@ -21,13 +21,13 @@ Hub](https://hub.docker.com/), le registre par défaut de `docker`, nous allons
devoir nous plier à leur mécanisme d'authentification : chaque requête au devoir nous plier à leur mécanisme d'authentification : chaque requête au
registre doit être effectuée avec un jeton, que l'on obtient en s'authentifiant registre doit être effectuée avec un jeton, que l'on obtient en s'authentifiant
auprès d'un service dédié. Ce service peut délivrer un jeton sans authentifier auprès d'un service dédié. Ce service peut délivrer un jeton sans authentifier
l'interlocuteur, en restant anonyme ; dans ce cas, on ne pourra accéder qu'aux l'interlocuteur, en restant anonyme ; dans ce cas, on ne pourra accéder qu'aux
images publiques. Ça tombe bien, c'est ce qui nous intéresse aujourd'hui ! images publiques. Ça tombe bien, c'est ce qui nous intéresse aujourd'hui !
Il n'en reste pas moins que le jeton est forgé pour un service donné (dans Il n'en reste pas moins que le jeton est forgé pour un service donné (ici
notre cas `registry.docker.io`) et avec un objectif bien cerné (pour nous, on `registry.docker.io`) et avec un objectif bien cerné (pour nous, on souhaite
souhaite récupérer le contenu du dépôt[^quiddepot] `hello-world` : récupérer le contenu du dépôt[^quiddepot] `hello-world` : <span
<span lang="en-US">`repository:hello-world:pull`</span>). Ce qui nous donne : lang="en-US">`repository:hello-world:pull`</span>). Ce qui nous donne :
[^quiddepot]: Dans un registre, les fichiers qui composent l'image forment un [^quiddepot]: Dans un registre, les fichiers qui composent l'image forment un
dépôt (*repository*). dépôt (*repository*).
@ -58,7 +58,11 @@ Avec `jq`, on peut l'extraire grâce à :
``` ```
</div> </div>
**Attention :** le token expire ! Pensez à le renouveler régulièrement. ::::: {.warning}
Le token expire ! Pensez à le renouveler régulièrement.
:::::
En cas d'erreur inexplicable, vous pouvez ajouter un `-v` à la ligne de En cas d'erreur inexplicable, vous pouvez ajouter un `-v` à la ligne de
commande `curl`, afin d'afficher les en-têtes. Prêtez une attention toute commande `curl`, afin d'afficher les en-têtes. Prêtez une attention toute
@ -94,12 +98,12 @@ système d'exploitation :
curl -s \ curl -s \
-H "Authorization: Bearer ${TOKEN}" \ -H "Authorization: Bearer ${TOKEN}" \
-H "Accept: ${MEDIATYPE}" \ -H "Accept: ${MEDIATYPE}" \
"https://registry-1.docker.io/v2/library/hello-world/manifests/${MANIFEST_DIGEST}" | jq . "https://registry-1.docker.io/v2/library/hello-world/manifests/${MNFST_DGST}"
``` ```
</div> </div>
Nous voici donc maintenant avec le manifest de notre image. Nous pouvons Nous voici donc maintenant avec le manifest de notre image. Nous pouvons
constater qu'il n'a bien qu'une seule couche, ouf ! constater qu'il n'a bien qu'une seule couche, ouf !
## Récupération de la configuration et de la première couche ## Récupération de la configuration et de la première couche
@ -115,7 +119,7 @@ Pour récupérer la configuration de l'image :
```bash ```bash
curl -s --location \ curl -s --location \
-H "Authorization: Bearer ${TOKEN}" \ -H "Authorization: Bearer ${TOKEN}" \
"https://registry-1.docker.io/v2/library/hello-world/blobs/${CONFIG_DIGEST}" | jq . "https://registry-1.docker.io/v2/library/hello-world/blobs/${CONFIG_DIGEST}"
``` ```
</div> </div>
@ -132,9 +136,11 @@ wget --header "Authorization: Bearer ${TOKEN}" \
## Extraction ## Extraction
Le type indiqué par le manifest pour cette couche était Le type indiqué par le manifest pour cette couche était :
`application/vnd.docker.image.rootfs.diff.tar.gzip`, il s'agit donc d'une
tarball compressée au format gzip : application/vnd.docker.image.rootfs.diff.tar.gzip
Il s'agit donc d'une tarball compressée au format gzip :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -179,7 +185,7 @@ Pensez également à tester avec d'autres images, comme par exemple
`nemunaire/youp0m`. Il vous faudra alors extraire plusieurs couches. `nemunaire/youp0m`. Il vous faudra alors extraire plusieurs couches.
Pour gérer les différentes couches, vous pouvez utiliser une stratégie Pour gérer les différentes couches, vous pouvez utiliser une stratégie
similaire au driver `vfs` : en extrayant chaque tarball l'une au dessus de similaire au driver `vfs` : en extrayant chaque tarball l'une au dessus de
l'autre, en essayant de gérer les *whiteout files*. Ou bien en suivant le l'autre, en essayant de gérer les *whiteout files*. Ou bien en suivant le
driver `overlayfs`, en montant un système de fichier à chaque couche (dans ce driver `overlayfs`, en montant un système de fichier à chaque couche (dans ce
cas, votre script devra être lancé en `root`). cas, votre script devra être lancé en `root`).

View file

@ -22,13 +22,13 @@ essayer de lancer un shell `alpine` avec un volume dans notre home.
Vous devriez avoir le binaire `runc` ou `docker-runc`. Si ce n'est pas le cas, Vous devriez avoir le binaire `runc` ou `docker-runc`. Si ce n'est pas le cas,
vous pouvez télécharger la dernière version : vous pouvez télécharger la dernière version :
<https://github.com/opencontainers/runc/releases>. La 1.0.0-rc92 est Ok. <https://github.com/opencontainers/runc/releases>.
## Extraction du rootfs ## Extraction du rootfs
À l'aide du script d'extraction de registre réalisé dans le TP 3, extrayons le À l'aide du script d'extraction de registre déjà réalisé, extrayons le
rootfs d'alpine : `library/alpine` dans le registre Docker. *rootfs* d'alpine : `library/alpine` dans le registre Docker.
Si vous n'avez pas eu le temps de terminer le script d'extraction, vous pouvez Si vous n'avez pas eu le temps de terminer le script d'extraction, vous pouvez
utiliser : utiliser :
@ -55,9 +55,7 @@ runc spec
Pour savoir à quoi correspondent tous ces éléments, vous pouvez consulter : Pour savoir à quoi correspondent tous ces éléments, vous pouvez consulter :
<https://github.com/opencontainers/runtime-spec/blob/master/config.md> <https://github.com/opencontainers/runtime-spec/blob/master/config.md>
Nous verrons dans les prochains TP, plus en détails tout ce qui porte sur les Rassurez-vous, il n'y a que très peu de champs à modifier.
*namespaces*, rassurez-vous, il n'y a que très peu de champs à modifier
aujourd'hui.
## Test brut ## Test brut
@ -143,8 +141,8 @@ stocker les photos (dossier `/srv/images`)[^chmod].
simple pour l'instant serait d'attribuer les permissions `0777` à la simple pour l'instant serait d'attribuer les permissions `0777` à la
source, temporairement. source, temporairement.
Pour ce TP, considérez que vous avez réussi si vous voyez s'afficher : Pour cette étape, Considérez que vous avez réussi si vous voyez s'afficher :
> `Ready, listening on :8080` > `Ready, listening on :8080`
Il faudra attendre les TP suivants pour avoir du réseau dans notre conteneur. On ne pourra pas tester davantage sans avoir du réseau dans notre conteneur.

View file

@ -10,10 +10,10 @@ machine hébergeant des conteneurs, car cela lui apporte des garanties quant à
l'effort de cloisonnement mis en place. l'effort de cloisonnement mis en place.
Mais doit-on pour autant s'arrêter là et considérer que nous avons réglé Mais doit-on pour autant s'arrêter là et considérer que nous avons réglé
l'ensemble des problématiques de sécurité liées aux conteneurs ? l'ensemble des problématiques de sécurité liées aux conteneurs ?
Évidemment, non : une fois nos services lancés dans des conteneurs, il ne sont Évidemment, non : une fois nos services lancés dans des conteneurs, il ne sont
pas moins exposés aux bugs et autres failles applicatives ; qu'elles soient pas moins exposés aux bugs et autres failles applicatives ; qu'elles soient
dans notre code ou celui d'une bibliothèque, accessible par rebond, ... dans notre code ou celui d'une bibliothèque, accessible par rebond, ...
Il est donc primordial de ne pas laisser ses conteneurs à l'abandon une fois Il est donc primordial de ne pas laisser ses conteneurs à l'abandon une fois
@ -23,7 +23,7 @@ image telle que Debian, Ubuntu ou Redhat n'apparaît que pour cela) ou bien
lorsqu'un des programmes ou l'une des bibliothèques que l'on a installés lorsqu'un des programmes ou l'une des bibliothèques que l'on a installés
ensuite est mise à jour. ensuite est mise à jour.
Convaincu ? Cela sonne encore comme des bonnes pratiques difficiles à mettre en Convaincu ? Cela sonne encore comme des bonnes pratiques difficiles à mettre en
œuvre, pouvant mettre en péril tout un système d'information. Pour s'en œuvre, pouvant mettre en péril tout un système d'information. Pour s'en
protéger, nous allons avoir besoin de réaliser à intervalles réguliers une protéger, nous allons avoir besoin de réaliser à intervalles réguliers une
analyse statique de nos conteneurs. analyse statique de nos conteneurs.
@ -42,9 +42,9 @@ automatiquement) les images que l'on publie sur un registre public, sans
oublier de mettre à jour l'image de base. oublier de mettre à jour l'image de base.
D'ailleurs, avez-vous vérifié qu'une mise à jour de l'image `nemunaire/youp0m` D'ailleurs, avez-vous vérifié qu'une mise à jour de l'image `nemunaire/youp0m`
n'était pas disponible depuis que vous avez commencé à l'utiliser ? Docker ne n'était pas disponible depuis que vous avez commencé à l'utiliser ? Docker ne
vérifie jamais si une mise à jour des images que vous avez précédemment vérifie jamais si une mise à jour des images que vous avez précédemment
téléchargées. Pensez donc régulièrement à appeler : téléchargées. Pensez donc régulièrement à appeler :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -65,10 +65,11 @@ si vous n'en avez pas, nous verrons dans la section suivante `trivy` qui permet
de réaliser ses scans directement sur notre machine, sans passer par un de réaliser ses scans directement sur notre machine, sans passer par un
intermédiaire. intermédiaire.
#### Attention {-} ::::: {.warning}
Par cette méthode, vous êtes limité à 10 scans par mois. Par cette méthode, vous êtes limité à 10 scans par mois.
:::::
### Installation du plugin ### Installation du plugin
@ -82,13 +83,14 @@ préalablement connecté à votre compte Docker avec la commande `docker login`.
Comme `docker scan` est un plugin, suivant la méthode d'installation que vous Comme `docker scan` est un plugin, suivant la méthode d'installation que vous
avez suivie, il n'a pas forcément été installé. Si vous obtenez un message avez suivie, il n'a pas forcément été installé. Si vous obtenez un message
d'erreur en lançant la commande, [voici comment récupérer le plugin et d'erreur en lançant la commande, [voici comment récupérer le plugin et
l'installer manuellement :](https://github.com/docker/scan-cli-plugin#on-linux) l'installer manuellement :](https://github.com/docker/scan-cli-plugin#on-linux)
<div lang="en-US"> <div lang="en-US">
``` ```
mkdir -p ~/.docker/cli-plugins mkdir -p ~/.docker/cli-plugins
curl https://github.com/docker/scan-cli-plugin/releases/latest/download/docker-scan_linux_amd64 \ curl -L -s -S -o ~/.docker/cli-plugins/docker-scan \
-L -s -S -o ~/.docker/cli-plugins/docker-scan https://github.com/docker/scan-cli-plugin/releases/\
latest/download/docker-scan_linux_amd64
chmod +x ~/.docker/cli-plugins/docker-scan chmod +x ~/.docker/cli-plugins/docker-scan
``` ```
</div> </div>
@ -96,7 +98,7 @@ chmod +x ~/.docker/cli-plugins/docker-scan
### Utilisation ### Utilisation
Une fois le plugin installé et la licence du service acceptée, nous pouvons Une fois le plugin installé et la licence du service acceptée, nous pouvons
commencer notre analyse : commencer notre analyse :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -112,7 +114,8 @@ Base image: alpine:3.14.2
✓ Tested 16 dependencies for known vulnerabilities, no vulnerable paths found. ✓ Tested 16 dependencies for known vulnerabilities, no vulnerable paths found.
According to our scan, you are currently using the most secure version of the selected base image According to our scan, you are currently using the most secure version of
the selected base image
``` ```
</div> </div>
@ -128,10 +131,10 @@ Testing mysql...
✗ High severity vulnerability found in gcc-8/libstdc++6 ✗ High severity vulnerability found in gcc-8/libstdc++6
Description: Insufficient Entropy Description: Insufficient Entropy
Info: https://snyk.io/vuln/SNYK-DEBIAN10-GCC8-469413 Info: https://snyk.io/vuln/SNYK-DEBIAN10-GCC8-469413
Introduced through: apt@1.8.2.3, mysql-community/mysql-community-client@8.0.26-1debian10, mysql-community/mysql-community-server-core@8.0.26-1debian10, mecab-ipadic@2.7.0-20070801+main-2.1, meta-common-packages@meta Introduced through: apt@1.8.2.3, mysql-community/mysql-community-client@[...]
From: apt@1.8.2.3 > gcc-8/libstdc++6@8.3.0-6 From: apt@1.8.2.3 > gcc-8/libstdc++6@8.3.0-6
From: mysql-community/mysql-community-client@8.0.26-1debian10 > gcc-8/libstdc++6@8.3.0-6 From: mysql-community/mysql-community-client@8.0.26-1debian10 > gcc-8[...]
From: mysql-community/mysql-community-server-core@8.0.26-1debian10 > gcc-8/libstdc++6@8.3.0-6 From: mysql-community/mysql-community-server-core@8.0.26-1debian10 > gcc-8[...]
and 7 more... and 7 more...
Image layer: Introduced by your base image (mysql:8.0.26) Image layer: Introduced by your base image (mysql:8.0.26)
@ -143,11 +146,12 @@ Base image: mysql:8.0.26
Tested 135 dependencies for known vulnerabilities, found 79 vulnerabilities. Tested 135 dependencies for known vulnerabilities, found 79 vulnerabilities.
According to our scan, you are currently using the most secure version of the selected base image According to our scan, you are currently using the most secure version of
the selected base image
``` ```
</div> </div>
Ce dernier exemple est sans appel : `mysql` est une image officielle, et sa Ce dernier exemple est sans appel : `mysql` est une image officielle, et sa
dernière version à l'écriture de ses lignes contient pas moins de 79 dernière version à l'écriture de ses lignes contient pas moins de 79
vulnérabilités dont 11 *high*. vulnérabilités dont 11 *high*.
@ -168,7 +172,7 @@ un certain nombre d'arguments, notamment le nom de l'image à analyser.
### Utilisation ### Utilisation
Tentons à nouveau d'analyser l'image `mysql` : Tentons à nouveau d'analyser l'image `mysql` :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -189,7 +193,7 @@ Les résultats sont un peu différents qu'avec `docker scan`, mais on constate
que l'image `mysql` contient vraiment de nombreuses vulnérabilités. Même si que l'image `mysql` contient vraiment de nombreuses vulnérabilités. Même si
elles ne sont heureusement pas forcément exploitable directement. elles ne sont heureusement pas forcément exploitable directement.
Voyons maintenant s'il y a des différentes avec l'image `nemunaire/fic-admin` : Voyons maintenant s'il y a des différentes avec l'image `nemunaire/fic-admin` :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -217,7 +221,7 @@ vulnérabilités de l'image, a aussi fait une analyse des dépendances du binair
`/srv/admin`. `/srv/admin`.
Trivy est en effet capable de rechercher des vulnérabilités par rapport aux Trivy est en effet capable de rechercher des vulnérabilités par rapport aux
dépendances connues de certains langages : Python, PHP, Node.js, .NET, Java, dépendances connues de certains langages : Python, PHP, Node.js, .NET, Java,
Go, ... Go, ...
@ -225,7 +229,7 @@ Go, ...
Pour éviter de surcharger les serveurs de distributions de la base de données Pour éviter de surcharger les serveurs de distributions de la base de données
de vulnérabilités, nous devrions utiliser un cache pour faire nos de vulnérabilités, nous devrions utiliser un cache pour faire nos
analyses. Préférez lancer `trivy` avec les options suivantes : analyses. Préférez lancer `trivy` avec les options suivantes :
<div lang="en-US"> <div lang="en-US">
``` ```
@ -242,7 +246,7 @@ pouvoir l'exporter pour l'afficher dans un navigateur (par exemple pour le
mettre à disposition des développeurs, lors d'une analyse automatique). mettre à disposition des développeurs, lors d'une analyse automatique).
Pour ce faire, on peut ajouter les options suivantes à la ligne de commande de Pour ce faire, on peut ajouter les options suivantes à la ligne de commande de
notre conteneur : notre conteneur :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -253,8 +257,6 @@ notre conteneur :
En redirigeant la sortie standard vers un fichier, vous pourrez l'ouvrir dans En redirigeant la sortie standard vers un fichier, vous pourrez l'ouvrir dans
votre navigateur favori. votre navigateur favori.
--- ![Scan de vulnérabilités sur le registre Quay.io](quay-vulns.png){ width=80% }
![Scan de vulnérabilités sur le registre Quay.io](quay-vulns.png){ width=90% }
## Clair ## Clair

View file

@ -1,23 +1,21 @@
\newpage \newpage
Création du cluster Création du cluster
=================== -------------------
## Le provisionnement de machine Pour travailler sur un cluster, il faut avoir plusieurs machines ... au moins
plus d'une !
Pour travailler sur un cluster, il faut avoir plusieurs machines ... au moins
plus d'une !
Mais qui dit plusieurs machines, dit généralement de nombreuses installations à Mais qui dit plusieurs machines, dit généralement de nombreuses installations à
faire, de nombreuses configurations à partager, etc. Tout ce qu'un faire, de nombreuses configurations à partager, etc. Tout ce qu'un
administrateur système redoute : du travail ! administrateur système redoute : du travail !
Évidemment, de nombreuses solutions existent pour travailler moins, tout en Évidemment, de nombreuses solutions existent pour travailler moins, tout en
déployant plus et de manière plus fiable ! On peut parler déployant plus et de manière plus fiable ! On peut parler
d'[`ansible`](https://www.ansible.com/), de d'[`ansible`](https://www.ansible.com/), de
[`chef`](https://docs.chef.io/provisioning.html), ou encore de [`chef`](https://docs.chef.io/provisioning.html), ou encore de
[`puppet`](https://puppet.com/products/capabilities/automated-provisioning), [`puppet`](https://puppet.com/products/capabilities/automated-provisioning), ...
... Toutes ces solutions permettent d'obtenir des configurations finement Toutes ces solutions permettent d'obtenir des configurations finement
personnalisées, mais nécessitent une phase d'apprentissage plutôt lourde. personnalisées, mais nécessitent une phase d'apprentissage plutôt lourde.
Comme nous voulons lancer des conteneurs, les machines à provisionner n'ont pas Comme nous voulons lancer des conteneurs, les machines à provisionner n'ont pas
@ -25,9 +23,7 @@ besoin de configuration bien particulière et les seuls paquets importants sont
une version récente de `docker` et ses dépendances. une version récente de `docker` et ses dépendances.
## Provisionner des machines ... ### Provisionner des machines ...
### Automagiquement
La solution magique consiste à passer par `docker-machine` pour créer des La solution magique consiste à passer par `docker-machine` pour créer des
machines virtuelles automatiquement provisionnées avec Docker. machines virtuelles automatiquement provisionnées avec Docker.
@ -38,21 +34,20 @@ virtuelles. Si votre machine Linux est en fait une machine virtuelle hébergée
par VirtualBox sous Windows, vous allez sans doute préférer la deuxième par VirtualBox sous Windows, vous allez sans doute préférer la deuxième
solution, que d'utiliser PowerShell et Docker4Windows[^amazon]. solution, que d'utiliser PowerShell et Docker4Windows[^amazon].
[^amazon]: Vous pouvez aussi vous inscrire sur [^amazon]: Vous pouvez aussi vous inscrire sur [Amazon Web
[Amazon Web Services](https://aws.amazon.com/), `docker-machine` est Services](https://aws.amazon.com/) <https://aws.amazon.com/>,
capable, à partir de vos `docker-machine` est capable, à partir de vos clefs d'API, de créer et
[clefs d'API](https://docs.docker.com/machine/examples/aws/), de créer et lancer des machines dans le cloud ! Et ce n'est pas le seul service de
lancer des machines dans le cloud ! Et ce n'est pas le seul service de cloud supporté !
[cloud supporté](https://docs.docker.com/machine/drivers/) !
#### Créer une machine ##### Créer une machine {-}
Pour créer une nouvelle machine, nous allons utiliser la commande Pour créer une nouvelle machine, nous allons utiliser la commande
`docker-machine create`, en prenant soin de préciser le pilote à utiliser, les `docker-machine create`, en prenant soin de préciser le pilote à utiliser, les
éventuelles options que prend ce pilote, ainsi que le nom que vous souhaitez éventuelles options que prend ce pilote, ainsi que le nom que vous souhaitez
donner à cette machine (les machines ne sont pas considérées comme jetables, donner à cette machine (les machines ne sont pas considérées comme jetables,
leur nom vous permettra par exemple de relancer une machine plus tard) : leur nom vous permettra par exemple de relancer une machine plus tard) :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -61,34 +56,37 @@ docker-machine create --driver virtualbox echinoidea
</div> </div>
Consultez la section suivante, réservée aux gens qui ne peuvent pas passer par Consultez la section suivante, réservée aux gens qui ne peuvent pas passer par
`docker-machine` si vous souhaitez avoir plus d'information sur ce que fait `docker-machine`, si vous souhaitez avoir plus d'information sur ce que fait
cette commande. cette commande.
#### Commandes usuelles de `docker-machine` ##### Commandes usuelles de `docker-machine` {-}
De la même manière que `docker`, vous pouvez lister les machines connues De la même manière que `docker`, vous pouvez lister les machines connues
(`ls`), changer leur état d'exécution (`start`/`stop`/`kill`/`restart`) ou encore supprimer la machine (`rm`) (`ls`), changer leur état d'exécution (`start`/`stop`/`kill`/`restart`) ou
encore supprimer une machine (`rm`).
Si vous avez besoin d'obtenir un shell : `docker-machine ssh $NAME` et Si vous avez besoin d'obtenir un shell : `docker-machine ssh $NAME` et
évidemment la commande `scp` s'utilise de la même manière, pour transférer des évidemment la commande `scp` s'utilise de la même manière, pour transférer des
fichiers. fichiers.
#### Utilisation avec Docker ##### Utilisation avec Docker {-}
Rappelez-vous, au cours précédent, nous avions évoqué le fait que le deamon Nous avons déjà évoqué le fait que le deamon pouvait ne pas se trouver sur la
pouvait ne pas se trouver sur la même machine que le client `docker`. Eh bien même machine que le client `docker`. Eh bien avec `docker-machine` cela prend
avec `docker-machine` cela prend tout son sens, car vous pouvez très facilement tout son sens, car vous pouvez très facilement changer de daemon/machine avec
changer de daamon/machine avec une simple commande : une simple commande :
<div lang="en-US"> <div lang="en-US">
``` ```
42sh$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS
42sh$ eval $(docker-machine env echinoidea)
42sh$ docker container ls -a 42sh$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS CONTAINER ID IMAGE COMMAND CREATED STATUS
a814293b9f45 armbuild/busybox "/bin/sh" 18 seconds ago Up 10 minutes
0caddeed5037 armbuild/alpine "/bin/sh" 2 weeks ago Created 42sh$ eval $(docker-machine env echinoidea)
42sh$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS
a814293b9f45 armbuild/busybox "/bin/sh" 18 seconds ago Up 10 minutes
0caddeed5037 armbuild/alpine "/bin/sh" 2 weeks ago Created
``` ```
</div> </div>
@ -102,43 +100,44 @@ supprimer manuellement les variables qui ont été ajoutées par l'évaluation,
soit lancer `eval $(docker machine env -u)`. soit lancer `eval $(docker machine env -u)`.
### Automanuellement #### Derrière Docker Machine...
Si votre environnement ne vous permet pas d'utiliser `docker-machine`, vous Si votre environnement ne vous permet pas d'utiliser `docker-machine`, vous
pouvez vous contenter aujourd'hui de démarrer une ou deux autres machines pouvez vous contenter de démarrer une ou deux autres machines virtuelles sur le
virtuelles sur le même réseau que votre machine actuelle. même réseau que votre machine virtuelle.
Rassurez-vous, vous n'allez pas avoir besoin de refaire toute la phase Rassurez-vous, vous n'allez pas avoir besoin de refaire toute la phase
d'installation. Des contributeurs maintiennent une petite ISO ne contenant que d'installation. Des contributeurs ont conçu une petite image de CD ne contenant
le strict nécessaire pour utiliser Docker. C'est d'ailleurs cette ISO qui est que le strict nécessaire pour utiliser Docker. C'est d'ailleurs cette ISO qui
utilisé par `docker-machine` pour démarrer et configurer en un rien de temps est utilisée par `docker-machine` pour démarrer et configurer en un rien de
ses machines virtuelles. temps ses machines virtuelles.
1. Dans un premier temps, commençons par 1. Dans un premier temps, commençons par télécharger la dernière ISO de
[télécharger la dernière ISO de `boot2docker.iso`](https://github.com/boot2docker/boot2docker/releases/latest). `boot2docker.iso` :\
<https://github.com/boot2docker/boot2docker/releases/latest>
1. Ensuite, dans notre hyperviseur, créons deux nouvelles machines, avec 1. Ensuite, dans notre hyperviseur, créons deux nouvelles machines, avec
suffisamment de ressources pour pouvoir lancer des conteneurs. Ce n'est pas suffisamment de ressources pour pouvoir lancer des conteneurs. Ce n'est pas
parce que l'images que l'on va démarrer est petite, que l'on ne va pas parce que l'image que l'on va démarrer est petite que l'on ne va pas
pouvoir allouer beaucoup d'espace disque ou de RAM. pouvoir allouer beaucoup d'espace disque ou de RAM.
1. Lançons ensuite nos deux images, configurées pour démarrer sur l'image ISO 1. Lançons ensuite nos deux images, configurées pour démarrer sur l'image ISO
que l'on a téléchargée précédemment. que l'on a téléchargée précédemment.
1. Faisons un `ip a` pour connaître l'IP de la machine, nous devrions pouvoir 1. Faisons un `ip a` pour connaître l'IP de la machine, nous devrions pouvoir
s'y connecter en SSH avec l'utilisateur `docker` dont le mot de passe est nous y connecter en SSH avec l'utilisateur `docker` dont le mot de passe est
`tcuser`. `tcuser`.
Vous constaterez que le daemon `dockerd` est déjà lancé. `docker` est déjà Vous constaterez que le daemon `dockerd` est déjà lancé. `docker` est déjà
pleinement utilisable dans cette machine ! pleinement utilisable dans cette machine !
#### (Optionnel) Déporter le client Docker #### (Optionnel) Déporter le client Docker
Dans le suite de ce TP, nous n'allons taper que quelques commandes dans nos Dans la suite, nous n'allons taper que quelques commandes dans nos
machines virtuelles, il n'est donc pas primordial d'avoir configuré son machines virtuelles, il n'est donc pas primordial d'avoir configuré son
environnement pour utiliser localement les daemons Docker des machines environnement pour utiliser localement les daemons Docker des machines
virtuelles. Néanmoins, cela ne coûte rien de voir les procédures mise en œuvre. virtuelles. Néanmoins, cela ne coûte rien de voir les procédures mise en œuvre.
Commençons par voir sur quel port le daemon `dockerd` de notre machine Commençons par voir sur quel port le daemon `dockerd` de notre machine
virtuelle écoute : virtuelle écoute :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -148,26 +147,25 @@ tcp 0 0 :::2376 :::* 980/dockerd
``` ```
</div> </div>
Essayons de renseigner simplement cette configuration à notre client Docker : Essayons de renseigner simplement cette configuration à notre client Docker :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
(main) 42sh$ docker -H tcp://$VM1_IP:2376/ info (main) 42sh$ docker -H tcp://$VM1_IP:2376/ info
Get http://$VM1_IP:2376/v1.32/info: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x15\x03\x01\x00\x02\x02". Get http://$VM1_IP:2376/v1.32/info: net/http: transport connection broken
* Are you trying to connect to a TLS-enabled daemon without TLS? * Are you trying to connect to a TLS-enabled daemon without TLS?
``` ```
</div> </div>
En effet, Docker met tout en œuvre pour rendre compliqué l'utilisation En effet, Docker met tout en œuvre pour rendre compliquée l'utilisation
non-sécurisée de la plate-forme. Mais ils font également en sorte que la non-sécurisée de la plate-forme. Mais ils font également en sorte que la
sécurité soit la plus transparente et la moins contraignante possible pour sécurité soit la plus transparente et la moins contraignante possible pour
l'utilisateur, sans pour autant être faible. l'utilisateur, sans pour autant être faible.
Afin de contacter un daemon Docker distant, il est nécessaire présenter un Afin de contacter un daemon Docker distant, il est nécessaire présenter un
certificat client TLS approuvé par ce daemon (comme lorsque vous vous connectez certificat client TLS approuvé par ce daemon. Il est seulement nécessaire de
sur [Epitaf](https://www.epitaf.fr/moodle)). Il est également nécessaire de
vérifier le certificat présenté par le daemon, comme dans le cadre d'une vérifier le certificat présenté par le daemon, comme dans le cadre d'une
connexion TLS classique. connexion SSH classique.
Tout le nécessaire est déjà configuré au sein de `boot2docker`, pour nos tests, Tout le nécessaire est déjà configuré au sein de `boot2docker`, pour nos tests,
nous n'avons qu'à recopier la clef et les certificats en place. nous n'avons qu'à recopier la clef et les certificats en place.
@ -182,12 +180,12 @@ key.pem
``` ```
</div> </div>
Tentons maintenant de nous connecter au daemon distant en utilisant ces éléments : Tentons maintenant de nous connecter au daemon distant utilisant ces éléments:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
42sh$ DOCKER_CERT_PATH=remote/virt1/ docker -H tcp://$VM1_IP:2376/ --tlsverify info DOCKER_CERT_PATH=remote/vir1/ docker -H tcp://$VM1_IP:2376/ --tlsverify info
``` ```
</div> </div>
Vous pouvez effectuer la même opération pour la seconde VM. Nous pouvons effectuer la même opération pour la seconde machine virtuelle.

View file

@ -34,7 +34,7 @@ Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...). placer dans une tarball (pas d'archive ZIP, RAR, ...).
Voici une arborescence type (vous pourriez avoir des fichiers supplémentaires, Voici une arborescence type (vous pourriez avoir des fichiers supplémentaires,
cela dépendra de votre avancée dans le projet) : cela dépendra de votre avancée dans le projet) :
<div lang="en-US"> <div lang="en-US">
``` ```

View file

@ -1,42 +1,35 @@
\newpage
Mise en place Mise en place
============= -------------
Pour cette partie, nous allons avoir besoin de `docker-machine`, installons-le sur
notre machine hôte, même si ce n'est pas un Linux : le but va être de lancer
plusieurs machines virtuelles dédiées à Docker pour simuler un cluster.
## `docker-machine` Ce programme permet de simplifier la gestion de multiples environnements
Docker, comme par exmple lorsque l'on souhaite gérer un cluster de machines
Pour ce TP, nous allons avoir besoin de `docker-machine`, installez-le sur
votre machine hôte, même si ce n'est pas un Linux : le but va être de lancer
plusieurs machines virtuelles Docker pour simuler un cluster.
Ce programme permet de simplifier la gestion du multiples environnements
Docker, comme par exemple lorsque l'on souhaite gérer un cluster de machines
pour un projet. pour un projet.
Ainsi, il est possible de provisionner et gérer des machines hôtes sur les Ainsi, il est possible de provisionner et gérer des machines hôtes sur les
plates-formes de cloud habituelles. C'est également ce projet qui est à la base plates-formes de cloud habituelles. C'est également ce projet qui est à la base
de *Docker for Mac* et *Docker for Windows*, en permettant de lancer via, de *Docker Dektop*, en permettant de lancer via, respectivement, VirtualBox ou
respectivement, VirtualBox et Hyper-V, un environnement Linux prêt à être Hyper-V, un environnement Linux prêt à être utilisé avec Docker.
utilisé avec Docker.
### Par la distribution binaire ### Par la distribution binaire
L'équipe en charge de `docker-machine` met à disposition un exécutable compilé L'équipe en charge de `docker-machine` met à disposition un exécutable compilé
pour bon nombres d'environnements. Nous pouvons l'installer en suivant la pour bon nombre d'environnements. Nous pouvons l'installer en suivant la
procédure suivante : procédure suivante :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
curl -L https://github.com/docker/machine/releases/download/v0.15.0/docker-machine-Linux-x86_64 \ V=0.16.2
P=docker-machine-`uname -s`-`uname -m`
curl -L https://github.com/docker/machine/releases/download/v${V}/${P} \
> /usr/bin/docker-machine > /usr/bin/docker-machine
chmod +x /usr/bin/docker-machine chmod +x /usr/bin/docker-machine
``` ```
</div> </div>
Si vous êtes dans un environnement différent, jetez un œil à
[la documentation d'installation](https://docs.docker.com/machine/install-machine/).
### Support de KVM ### Support de KVM
@ -46,28 +39,30 @@ plug-ins.
Si vous utilisez KVM comme hyperviseur, vous allez avoir besoin d'installer le Si vous utilisez KVM comme hyperviseur, vous allez avoir besoin d'installer le
plugins plugins
[`docker-machine-kvm`](https://github.com/dhiltgen/docker-machine-kvm). Vous [`docker-machine-kvm`](https://github.com/machine-drivers/docker-machine-kvm). Vous
n'aurez qu'à suivre les instructions du n'aurez qu'à suivre les instructions du `README` :\
[`README`](https://github.com/dhiltgen/docker-machine-kvm/blob/master/README.md) <https://github.com/machine-drivers/docker-machine-kvm/>
!
Les autres plugins sont disponibles au sein de l'organisation Machine-Driver
sur GitHub :\
<https://github.com/machine-drivers/>
### Vérification du fonctionnement ### Vérification du fonctionnement
Comme avec Docker, nous pouvons vérifier le bon fonctionnement de Comme avec Docker, nous pouvons vérifier le bon fonctionnement de
`docker-machine` en exécutant la commande : `docker-machine` en exécutant la commande :
<div lang="en-US"> <div lang="en-US">
``` ```
42sh$ docker-machine version 42sh$ docker-machine version
docker-machine version 0.12.2, build 9371605 docker-machine version 0.16.2, build 9371605
``` ```
</div> </div>
## Play With Docker ### Play With Docker
Tout comme pour le TP précédent, si vous avez des difficultés pour réaliser les Si vous avez des difficultés pour réaliser les exercices sur votre machine,
exercices sur vos machines, vous pouvez utiliser le projet vous pouvez utiliser le projet [Play With
[Play With Docker](https://play-with-docker.com/) qui vous donnera accès à un Docker](https://play-with-docker.com/) qui vous donnera accès à un bac à sable
bac à sable avec lequel vous pourrez réaliser tous les exercices de ce TP. avec lequel vous pourrez réaliser tous les exercices de cette partie.

View file

@ -1,15 +1,15 @@
\newpage \newpage
Déploiement de services Déploiement de services
======================= -----------------------
## Services ? ### Services?
Une petite minute terminologie avant de continuer, car lorsque l'on passe sur Une petite minute terminologie avant de continuer, car lorsque l'on passe sur
les clusters de Docker, cela change un peu : les clusters de Docker, cela change un peu :
* une *tâche* correspond à **un** unique conteneur, lancé sur l'un des nœuds * une *tâche* correspond à **un** unique conteneur, lancé sur l'un des nœuds
*workers* du cluster ; *workers* du cluster;
* un *service* est un groupe de tâches (oui, les tâches du point précédent), * un *service* est un groupe de tâches (oui, les tâches du point précédent),
exécutant la même image. exécutant la même image.
@ -18,13 +18,13 @@ la haute-disponibilité ou pour répartir la charge.
<div lang="en-US"> <div lang="en-US">
### Hello world, again? #### Hello world, again?
</div> </div>
Non, pas d'hello-world ici, mais nous allons prendre en main les services avec Non, pas d'hello-world ici, mais nous allons prendre en main les services avec
un serveur web, qui sera bien plus représentatif de ce que l'on pourra obtenir. un serveur web, qui sera bien plus représentatif de ce que l'on pourra obtenir.
Précédemment, nous lancions notre serveur web favori avec : Précédemment, nous lancions notre serveur web favori avec:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -33,7 +33,7 @@ docker container run --name mywebs -d nginx
</div> </div>
La même commande, mais déployée à partir d'un nœud manager, vers un nœud La même commande, mais déployée à partir d'un nœud manager, vers un nœud
*workers*, est : *workers*, est:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -41,7 +41,7 @@ docker service create --name myWebS nginx
``` ```
</div> </div>
Allons-y, essayons ! Allons-y, essayons!
On peut consulter l'état du service avec, comme d'habitude `ls` : On peut consulter l'état du service avec, comme d'habitude `ls` :
@ -59,7 +59,7 @@ déployé, le tâche apparaît dans la liste des conteneurs !
Rien de très excitant pour le moment, car nous ne pouvons pas vraiment accéder Rien de très excitant pour le moment, car nous ne pouvons pas vraiment accéder
à notre serveur. Essayons de modifier sa configuration en direct, afin à notre serveur. Essayons de modifier sa configuration en direct, afin
d'ajouter une redirection de port : d'ajouter une redirection de port:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -71,13 +71,13 @@ docker service update --publish-add 80 myWebS
service sont stoppés puis, le manager voyant que le service n'est pas dans service sont stoppés puis, le manager voyant que le service n'est pas dans
l'état demandé, va lancer des tâches avec la nouvelle configuration. l'état demandé, va lancer des tâches avec la nouvelle configuration.
La commande `update` est très puissante : vous pouvez mettre à jour La commande `update` est très puissante: vous pouvez mettre à jour
pratiquement n'importe quel élément de configuration, y compris le nom de pratiquement n'importe quel élément de configuration, y compris le nom de
l'image ou son tag. Grâce à cela, faire des mises à jour se fait de manière l'image ou son tag. Grâce à cela, faire des mises à jour se fait de manière
transparente. transparente.
#### Magie du mesh ##### Magie du mesh {-}
Lorsque l'on publie un port de cette manière, chaque nœud du cluster devient un Lorsque l'on publie un port de cette manière, chaque nœud du cluster devient un
point d'entrée pour ce port, même si la tâche ne s'exécute pas sur ce nœud point d'entrée pour ce port, même si la tâche ne s'exécute pas sur ce nœud
@ -88,25 +88,26 @@ nœuds. Vous devriez voir la même page.
Lorsque plusieurs tâches s'exécutent pour ce service, le nœud d'entrée choisi Lorsque plusieurs tâches s'exécutent pour ce service, le nœud d'entrée choisi
selon un round-robin à quelle tâche il va diriger la requête. C'est grâce à ce selon un round-robin à quelle tâche il va diriger la requête. C'est grâce à ce
mécanisme qu'il est possible faire une répartition de charge très simplement. mécanisme qu'il est possible de faire de la répartition de charge très
simplement.
\vspace{1.5em} \vspace{1.5em}
Cette méthode n'est pas la seule permettant d'exposer des ports. Mais c'est Cette méthode n'est pas la seule permettant d'exposer des ports. Mais c'est
sans doute la plus intuitive. Si vous souhaitez en apprendre plus, vous deviez sans doute la plus intuitive. Si vous souhaitez en apprendre plus, vous devriez
consulter la consulter la documentation à ce sujet:\
[documentation à ce sujet](https://docs.docker.com/engine/swarm/networking/). <https://docs.docker.com/engine/swarm/networking/>
### Mise à l'échelle et placement #### Mise à l'échelle et placement
On parle depuis toute à l'heure de lancer plusieurs tâches pour le même On parle depuis toute à l'heure de lancer plusieurs tâches pour le même
service. La mise à l'échelle c'est ça : exécuter plusieurs conteneurs pour la service. La mise à l'échelle, c'est ça : exécuter plusieurs conteneurs pour la
même tâche afin de mieux répartir la charge, idéalement sur des machines même tâche afin de mieux répartir la charge, idéalement sur des machines
physique différentes. physiques différentes.
Ce qui se fait souvent avec beaucoup de douleur hors de Docker, se résume ici à Ce qui se fait souvent avec beaucoup de douleur hors de Docker, se résume ici
: à :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -122,21 +123,21 @@ docker service ps myWebS
``` ```
</div> </div>
nous montre bien, a priori 3 tâches en cours d'exécution pour ce service ! nous montre bien, a priori 3 tâches en cours d'exécution pour ce service!
Enfin, vous avez compris le principe ! Enfin, vous avez compris le principe!
## Stack ? ### Stack?
Refermons cette longue parenthèse et revenons-en au sujet du jour : la Refermons cette longue parenthèse et revenons-en au sujet du jour: la
supervision de nos machines. supervision de nos machines.
Une *stack* est un groupe de services. Un projet, par exemple un site web dans Une *stack* est un groupe de services. Un projet, par exemple un site web dans
son ensemble : frontend, API, base de données, ... son ensemble: frontend, API, base de données, ...
Notre système de monitoring est une *stack* lui aussi, d'ailleurs, nous pouvons Notre système de monitoring est une *stack* lui aussi, d'ailleurs, nous pouvons
la lancer grâce à notre `docker-compose.yml` : la lancer grâce à notre `docker-compose.yml`:
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -144,7 +145,7 @@ docker stack deploy --compose-file docker-compose.yml tic
``` ```
</div> </div>
### Règle de déploiement #### Règle de déploiement
Par rapport à `docker-compose`, nous pouvons indiquer dans ce fichier des Par rapport à `docker-compose`, nous pouvons indiquer dans ce fichier des
paramètres qui ne serviront qu'au déploiement de notre tâche. paramètres qui ne serviront qu'au déploiement de notre tâche.

View file

@ -1,61 +1,13 @@
\newpage \newpage
Déploiement de conteneurs Déploiement de conteneurs
========================= -------------------------
Historiquement, le passage d'une application en production ou simplement dans
un environnement de qualification, n'est pas toujours aisé. Parfois d'ailleurs,
on ne teste pas, on fait les modifications en production ... et à chaque
déploiement, on prie pour ne pas écraser une modification qui faisait que notre
projet tombait en marche dans cet environnement.
Déployer des conteneurs sur sa propre machine, c'est extrêmement simple
grâce. Et mieux encore, tout l'environnement étant contenu dans l'image, il
suffit de suivre les bonnes pratiques pour que le déploiement en production se
fasse de manière transparente.
## L'orchestration
Cependant, notons une différence de taille entre notre environnement de
développement sur nos machines locales et la production : les clients ! Pour
répondre de manière adéquate, il convient de dimensionner correctement les
machines, le nombre de conteneurs que chacune peut exécuter, en fonction de
caractéristiques (on privilégiera les machines avec des SSD pour les serveurs
de base de données par exemple), ...
Il n'est pas question pour un administrateur système de faire cette répartition
de la charge à la main : le nombre de critères à prendre en compte est beaucoup
trop grand, évolue sans cesse ; cela serait trop long s'il y a beaucoup de
conteneurs et de variété de machines.
Ce processus d'optimisation s'appelle l'*orchestration*. Il s'agit de réussir à
répartir au mieux les conteneurs sur les différentes machines disponibles.
Ce sujet fait l'objet de très nombreuses thèse depuis plusieurs années (avant
les conteneurs, c'était pour répartir les machines virtuelles entre différents
hôtes), et autant de projets disponibles. Citons par exemple
[Google Kubernetes](https://kubernetes.io),
[Hashicorp Nomad](https://www.nomadproject.io/) ou encore
[Apache Mesos](https://mesos.apache.org/), ...
Le point commun entre la plupart des orchestrateurs, c'est généralement leur
extrême complexité de mise en œuvre. Dans le cadre de notre TP, nous allons
plutôt utiliser l'orchestrateur intégré à Docker, dont la caractéristique
principale est sa simplicité[^dockerconEU2017].
[^dockerconEU2017]: À noter qu'une annonce faite à la Docker Con EU
2017 indique le début du support de Kubernetes au sein de Docker
EE, pouvant être utilisé en symbiose avec Swarm.
### Concepts clefs
Regroupés au sein d'un cluster (on parle de *swarm* pour Docker), chaque Regroupés au sein d'un cluster (on parle de *swarm* pour Docker), chaque
*Docker engine* représente un nœud (*node*) dans lequel on va déployer des *Docker engine* représente un nœud (*node*) dans lequel on va déployer des
*services*. *services*.
Certain nœud ont un rôle de *manager*, parmi ceux-ci, un seul est élu leader et Certain nœuds ont un rôle de *manager*, parmi ceux-ci, un seul est élu leader et
prendra les décisions d'orchestration. Les autres sont là pour prendre le prendra les décisions d'orchestration. Les autres sont là pour prendre le
relais en cas de dysfonctionnement sur le manager élu. relais en cas de dysfonctionnement sur le manager élu.
@ -66,15 +18,16 @@ cluster. En cas de crash d'un manager ou d'un *worker*, le (nouveau) manager
fera en sorte de redéployer les conteneurs perdus, afin de toujours maintenir fera en sorte de redéployer les conteneurs perdus, afin de toujours maintenir
le cluster dans l'état désiré. le cluster dans l'état désiré.
En terme de cluster, des tâches sont l'équivalent des conteneurs, hors de Swarm. En termes de cluster, des tâches sont l'équivalent des conteneurs, hors de
Swarm.
## Création du cluster Swarm ### Création du cluster Swarm
### Initialisation du cluster #### Initialisation du cluster
La première chose à faire, est d'initialiser un cluster swarm. Pour se faire, La première chose à faire est d'initialiser un cluster Swarm. Pour se faire,
ce n'est pas plus compliqué que de faire : ce n'est pas plus compliqué que de faire :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -88,14 +41,14 @@ cluster, afin de pouvoir lancer des tâches ... au moins sur lui-même en
attendant d'autres nœuds. attendant d'autres nœuds.
### Rejoindre le cluster #### Rejoindre un cluster
Pour rejoindre un cluster, il est nécessaire d'avoir le jeton associé à ce Pour rejoindre un cluster, il est nécessaire d'avoir le jeton associé à ce
cluster. cluster.
La commande pour rejoindre le cluster et contenant le jeton, est indiquée La commande pour rejoindre un cluster et contenant le jeton est iniquée
lorsque vous initialisez le cluster. Si vous avez raté la sortie de la lorsque vous initialisez le cluster. Si vous avez raté la sortie de la
commande, vous pouvez retrouver le jeton avec : commande, vous pouvez retrouver le jeton avec :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -106,17 +59,11 @@ docker swarm join-token worker
Lançons maintenant la commande `join` indiquée, sur une autre machine, en Lançons maintenant la commande `join` indiquée, sur une autre machine, en
utilisant `docker-machine`. utilisant `docker-machine`.
**Pro tips:** envoyez votre commande `join` à votre voisin qui a réussi à
provisionner plusieurs machines Docker (via `docker-machine` ou manuellement,
peu importe du moment que les VMs ont bien accès au même réseau que votre
*Swarm*[^avertVM]). Et soyez fair-play, attendez un peu avant de lancer
l'image `embano1/cpuburn` ;)
[^avertVM]: Si vous utilisez Docker dans une VM, il faut que celle-ci soit [^avertVM]: Si vous utilisez Docker dans une VM, il faut que celle-ci soit
configurée en mode bridge pour qu'elle soit sur le même sous-réseau. Il n'y configurée en mode bridge pour qu'elle soit sur le même sous-réseau. Il n'y
a pas de problème à avoir des nœuds *workers* derrière un NAT, mais il est a pas de problème à avoir des nœuds *workers* derrière un NAT, mais il est
primordial que les managers soient joignables. Vous pouvez tenter de faire primordial que les managers soient joignables. Vous pouvez tenter de faire
des redirections de ports, mais le résultat n'est pas garanti ! des redirections de ports, mais le résultat n'est pas garanti !
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -125,11 +72,12 @@ docker swarm join --token SWMTKN-1-...-... 10.10.10.42:2377
``` ```
</div> </div>
Une fois rejoint, vous devriez voir apparaître un nouveau nœud *worker* dans : Une fois rejoint, vous devriez voir apparaître un nouveau nœud *worker* dans :
<div lang="en-US"> <div lang="en-US">
``` ```
42sh$ eval $(docker-machine env -u) 42sh$ eval $(docker-machine env -u)
42sh$ docker node ls 42sh$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
y9skzvuf989hjrkciu8mnsy echinoidea Ready Active y9skzvuf989hjrkciu8mnsy echinoidea Ready Active
@ -138,21 +86,21 @@ ovgh6r32kgcbswb2we48br1 * wales Ready Active Leader
</div> </div>
### Rejoindre en tant que manager #### Rejoindre en tant que manager
Lorsqu'il est nécessaire d'avoir de la haute-disponibilité, on définit Lorsqu'il est nécessaire d'avoir de la haute-disponibilité, on définit
plusieurs managers. Cela permet qu'en cas de dysfonctionnement du manager, un plusieurs managers. Cela permet qu'en cas de dysfonctionnement du manager, un
nouveau manager soit élu. nouveau manager soit élu.
Nous n'allons pas faire rejoindre de manager supplémentaire durant ce TP, mais Nous n'allons pas faire rejoindre de manager supplémentaire à ce stade, mais
vous pouvez facilement expérimenter la chose en lançant 5 machines virtuelles vous pouvez facilement expérimenter la chose en lançant 5 machines virtuelles
et en définissant trois des cinq machines comme étant managers. et en définissant trois des cinq machines comme étant managers.
Pour que l'algorithme de consensus fonctionne de manière optimale, il convient Pour que l'algorithme de consensus fonctionne de manière optimale, il convient
toujours un nombre impair de managers, Docker en recommande 3 ou 5. La pire de toujours avoir un nombre impair de managers: Docker en recommande 3
configuration est avec deux managers, car si un tombe, il ne peut pas savoir si ou 5. La pire configuration est avec deux managers, car si l'un des deux tombe,
c'est lui qui est isolé (auquel cas il attendrait d'être à nouveau en ligne il ne peut pas savoir si c'est lui qui est isolé (auquel cas il attendrait
avant de se proclamer leader) ou si c'est l'autre manager qui est tombé. Avec d'être à nouveau en ligne avant de se procalmer leader) ou si c'est l'autre qui
trois managers, en cas de perte d'un manager, les deux restants peuvent est tombé. Avec trois managers, en cas de perte d'un manager, les deux restants
considérer qu'ils ont perdu le troisième et peuvent élire le nouveau manager peuvent considérer qu'ils ont perdu le troisième et peuvent élire le nouveau
entre-eux et continuer à faire vivre le cluster. manager entre eux et continuer à faire vivre le cluster.

View file

@ -6,7 +6,7 @@ institute: EPITA
date: Jeudi 18 octobre 2018 date: Jeudi 18 octobre 2018
abstract: | abstract: |
Dans la troisième partie de ce TP, nous allons orchestrer nos Dans la troisième partie de ce TP, nous allons orchestrer nos
conteneurs ! conteneurs !
\vspace{1em} \vspace{1em}
@ -21,4 +21,4 @@ abstract: |
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) [me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96)
faire signer votre clef et n'hésitez pas à [faire signer la 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/). vôtre](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
... ...

View file

@ -1,6 +1,6 @@
\newpage \newpage
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 Pour construire une image, nous ne sommes pas obligés de passer par une série
@ -22,7 +22,7 @@ l'intitulé d'une instruction (que l'on écrit généralement en majuscule), ell
est suivie de ses arguments. est suivie de ses arguments.
Dans notre exemple, nous utilisons `FROM`{.dockerfile} qui indique une image de Dans notre exemple, nous utilisons `FROM`{.dockerfile} qui indique une image de
départ à utiliser ; `RUN`{.dockerfile} est une commande qui sera exécutée dans départ à utiliser ; `RUN`{.dockerfile} est une commande qui sera exécutée dans
le conteneur, dans le but de le construire. le conteneur, dans le but de le construire.
Pour lancer la construction de la nouvelle image, créons un nouveau dossier ne Pour lancer la construction de la nouvelle image, créons un nouveau dossier ne
@ -136,9 +136,9 @@ Rendez-vous ensuite dans votre navigateur sur <http://localhost:49153/>.
#### À vous de jouer {-} #### À vous de jouer {-}
Utilisez l'instruction `COPY`{.dockerfile} pour afficher votre propre Utilisez l'instruction `COPY`{.dockerfile} pour afficher votre propre
`index.html` remplaçant celui installé de base par `nginx`. Si vous manquez `index.html` remplaçant celui installé de base par `nginx`. <!--Si vous manquez
d'inspiration, utilisez [cette page de compte à d'inspiration, utilisez [cette page de compte à
rebours](https://virli.nemunai.re/countdown.html). rebours](https://virli.nemunai.re/countdown.html).-->
### Les caches ### Les caches
@ -177,9 +177,10 @@ images), en haut du `Dockerfile`.
L'instruction `LABEL`{.dockerfile} permet d'ajouter une métadonnée à une image, L'instruction `LABEL`{.dockerfile} permet d'ajouter une métadonnée à une image,
sous forme de clef/valeur. sous forme de clef/valeur.
Une métadonnée Une métadonnée courante[^MAINTAINER] est d'indiquer le nom du
[courante](https://github.com/nginxinc/docker-nginx/blob/master/stable/debian/Dockerfile#L8) mainteneur de l'image :
est d'indiquer le nom du mainteneur de l'image :
[^MAINTAINER]: Voir par exemple : <https://github.com/nginxinc/docker-nginx/blob/master/stable/debian/Dockerfile#L8>
<div lang="en-US"> <div lang="en-US">
```dockerfile ```dockerfile
@ -221,15 +222,15 @@ retirez cette option pour voir ce qui ne va pas, ou utilisez la commande
`docker container logs`. `docker container logs`.
### Construire son application au moment de la construction du conteneur ? ### Construire son application au moment de la construction du conteneur ?
Comment faire lorsque l'on a besoin de compiler une application avant de Comment faire lorsque l'on a besoin de compiler une application avant de
l'intégrer dans le conteneur ? l'intégrer dans le conteneur ?
On peut vouloir lancer la compilation sur notre machine, mais cela ne sera pas 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 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 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 versions de ces outils existent, laquelle choisir ? ... Ok c'est trop
compliqué. compliqué.
D'un autre côté, si l'on fait cela dans un conteneur, celui-ci contiendra dans D'un autre côté, si l'on fait cela dans un conteneur, celui-ci contiendra dans
@ -300,7 +301,7 @@ sélectionnera ainsi avec l'option `--target` l'un ou l'autre en fonction de
l'environnement dans lequel on souhaite se déployer. l'environnement dans lequel on souhaite se déployer.
### D'autres instructions ? ### D'autres instructions ?
Consultez <https://docs.docker.com/engine/reference/builder/> pour la liste Consultez <https://docs.docker.com/engine/reference/builder/> pour la liste
complète des instructions reconnues. complète des instructions reconnues.
@ -310,12 +311,12 @@ complète des instructions reconnues.
Pour mettre en application tout ce que nous venons de voir, réalisons le 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 `Dockerfile` du service web [`youp0m`](https://you.p0m.fr/) que nous avons
utilisé la semaine dernière. déjà utilisé précédemment.
Pour réaliser ce genre de contribution, on ajoute généralement un `Dockerfile` Pour réaliser ce genre de contribution, on ajoute généralement un `Dockerfile`
à la racine du dépôt. à la racine du dépôt.
Vous pouvez cloner le dépôt de sources de `youp0m` à : Vous pouvez cloner le dépôt de sources de `youp0m` à :\
<https://git.nemunai.re/nemunaire/youp0m.git> <https://git.nemunai.re/nemunaire/youp0m.git>
Pour compiler le projet, vous pouvez utiliser dans votre `Dockerfile` Pour compiler le projet, vous pouvez utiliser dans votre `Dockerfile`

View file

@ -37,7 +37,7 @@ Hello world
</div> </div>
Dans ce premier cas, il n'y a pas d'argument après le nom de l'image, c'est Dans ce premier cas, il n'y a pas d'argument après le nom de l'image, c'est
donc le contenu de `CMD`{.dockerfile} qui est utilisé ; il est donc passé en donc le contenu de `CMD`{.dockerfile} qui est utilisé ; il est donc passé en
argument à l'`ENTRYPOINT`{.dockerfile}. Concrètement, la première ligne de argument à l'`ENTRYPOINT`{.dockerfile}. Concrètement, la première ligne de
commande exécutée est : commande exécutée est :

View file

@ -27,8 +27,8 @@ dépendances ont bien été enregistrée.
Ce fichier fonctionne de la même manière que le `.gitignore` : vous pouvez Ce fichier fonctionne de la même manière que le `.gitignore` : vous pouvez
utiliser du globing. utiliser du globing.
Pour plus d'informations, vous pouvez consulter la documentation accessible à Pour plus d'informations, vous pouvez consulter la documentation accessible à\
<https://docs.docker.com/engine/reference/builder/#dockerignore-file>. <https://docs.docker.com/engine/reference/builder/#dockerignore-file>
### N'installez rien de superflu ### N'installez rien de superflu
@ -40,7 +40,7 @@ comme serveur web. Un autre conteneur pourra contenir cet éditeur de texte dans
les cas où vous avez besoin de modifier des données. les cas où vous avez besoin de modifier des données.
En plus, cela réduira le temps de construction et la taille des images En plus, cela réduira le temps de construction et la taille des images
produites ! produites !
Avec `apt` par exemple, vous pouvez ajouter l'option `--no-install-recommends` Avec `apt` par exemple, vous pouvez ajouter l'option `--no-install-recommends`
lors vous installer un paquet qui vient avec de nombreuses recommandations lors vous installer un paquet qui vient avec de nombreuses recommandations
@ -64,7 +64,7 @@ place.
#### Allez à la ligne pour séparer les longues lignes de commandes complexes\ #### Allez à la ligne pour séparer les longues lignes de commandes complexes\
Aérez vos `Dockerfile` ! Aérez vos `Dockerfile` !
N'hésitez pas à commenter et séparer les blocs logiques ensemble, comme lorsque N'hésitez pas à commenter et séparer les blocs logiques ensemble, comme lorsque
vous codez. vous codez.
@ -176,7 +176,7 @@ CMD ["-g", "daemon", "off;"]
- Vous pouvez aussi utiliser un script qui servira à faire les initialisations - Vous pouvez aussi utiliser un script qui servira à faire les initialisations
ou les configurations nécessaire au bon fonctionnement du conteneur ou les configurations nécessaire au bon fonctionnement du conteneur
(rappelez-vous, il doit être éphémère !). Par exemple, le `Dockerfile` pour (rappelez-vous, il doit être éphémère !). Par exemple, le `Dockerfile` pour
l'image de PostgreSQL possède cet entrypoint : l'image de PostgreSQL possède cet entrypoint :
<div lang="en-US"> <div lang="en-US">

Some files were not shown because too many files have changed in this diff Show more