tutorials: improve theme + use pandoc 2

This commit is contained in:
nemunaire 2018-11-16 02:38:41 +01:00
parent de21be218a
commit d25af4fdb2
65 changed files with 1281 additions and 1292 deletions

View file

@ -1,18 +1,6 @@
include ../pandoc-opts.mk
SOURCES = tutorial.md installation.md chroot.md pseudofs.md capabilities.md cgroups.md oom.md seccomp.md project-intro.md project-body.md project-rendu.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=fr-FR \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
-M colorlinks=true \
-M linkcolor="black" \
--include-in-header=../header.tex
all: tutorial.pdf

View file

@ -78,25 +78,25 @@ Sous Linux, les attributs sont regroupés dans des espaces de noms :
Par exemple, on peut définir un attribut sur un fichier comme cela :
<div lang="en-US">
```shell
42sh$ echo 'Hello World!' > toto
42sh$ setfattr -n user.foo -v bar toto
42sh$ getfattr -d toto
# file: toto
user.foo="bar"
```bash
42sh$ echo 'Hello World!' > toto
42sh$ setfattr -n user.foo -v bar toto
42sh$ getfattr -d toto
# file: toto
user.foo="bar"
```
</div>
Encore plus fort, vous pouvez utiliser les ACL POSIX :
<div lang="en-US">
```shell
42sh$ sudo chown root:root toto && sudo chmod o-r toto
42sh$ cat toto
cat: toto: Permission denied
42sh$ sudo setfattr -m u:$USER:r toto
42sh$ cat toto
Hello World!
```bash
42sh$ sudo chown root:root toto && sudo chmod o-r toto
42sh$ cat toto
cat: toto: Permission denied
42sh$ sudo setfattr -m u:$USER:r toto
42sh$ cat toto
Hello World!
```
</div>
@ -106,10 +106,10 @@ les ACL POSIX vous autorisent à le lire.
Vous pouvez voir ces attributs avec la commande :
<div lang="en-US">
```shell
42sh$ getfattr -d -m "^system" toto
# file: toto
system.posix_acl_access=0sgAAEAD/////AgAEOgDAEAA/////xAABAD////8=
```bash
42sh$ getfattr -d -m "^system" toto
# file: toto
system.posix_acl_access=0sgAAEAD/////AgAEOgDAEAA/////xAABAD////8=
```
</div>
@ -126,19 +126,19 @@ l'utilisation de cet attribut auquel on accroîtrait l'ensemble des
Si votre distribution profite de ces attributs étendus, vous devriez obtenir :
<div lang="en-US">
```shell
42sh$ getfattr -d -m "^security" $(which ping)
# file: bin/ping
security.capability=0sAQAAAgAgAAAAAAAAAAAAAAAAAAA=
```bash
42sh$ getfattr -d -m "^security" $(which ping)
# file: bin/ping
security.capability=0sAQAAAgAgAAAAAAAAAAAAAAAAAAA=
```
</div>
Ou, dans sa version plus lisible :
<div lang="en-US">
```shell
42sh$ getcap $(which ping)
/bin/ping = cap_net_raw+ep
```bash
42sh$ getcap $(which ping)
/bin/ping = cap_net_raw+ep
```
</div>
@ -149,39 +149,39 @@ Ou, dans sa version plus lisible :
d'un processus :
<div lang="en-US">
```shell
42sh$ ./view_caps 1
cap_user_header_t
-----------------
Version: 20080522
PID: 1
```
42sh$ ./view_caps 1
cap_user_header_t
-----------------
Version: 20080522
PID: 1
cap_user_data_t
---------------
effective: 0x3fffffffff
CAP_AUDIT_CONTROL
CAP_AUDIT_READ
[...]
CAP_SYS_TIME
CAP_SYS_TTY_CONFIG
CAP_SYSLOG
CAP_WAKE_ALARM
permitted: 0x3fffffffff
CAP_AUDIT_CONTROL
CAP_AUDIT_READ
[...]
CAP_SYS_TIME
CAP_SYS_TTY_CONFIG
CAP_SYSLOG
CAP_WAKE_ALARM
inheritable: 0x0
cap_user_data_t
---------------
effective: 0x3fffffffff
CAP_AUDIT_CONTROL
CAP_AUDIT_READ
[...]
CAP_SYS_TIME
CAP_SYS_TTY_CONFIG
CAP_SYSLOG
CAP_WAKE_ALARM
permitted: 0x3fffffffff
CAP_AUDIT_CONTROL
CAP_AUDIT_READ
[...]
CAP_SYS_TIME
CAP_SYS_TTY_CONFIG
CAP_SYSLOG
CAP_WAKE_ALARM
inheritable: 0x0
```
</div>
Astuces : `capget(2)`, X-macros, ...
## Pour aller plus loin
## Pour aller plus loin {-}
Je vous recommande la lecture des *man* suivants :

View file

@ -23,9 +23,9 @@ pas de dossier `freezer` ou si celui-ci est vide, montez-le en suivant la
procédure suivante :
<div lang="en-US">
```
mkdir /sys/fs/cgroup/freezer/
mount -t cgroup -o freezer none /sys/fs/cgroup/freezer/
```bash
mkdir /sys/fs/cgroup/freezer/
mount -t cgroup -o freezer none /sys/fs/cgroup/freezer/
```
</div>
@ -42,9 +42,9 @@ Pour ce faire, il suffit de créer un nouveau dossier dans un groupe existant,
par exemple la racine :
<div lang="en-US">
```
mkdir /sys/fs/cgroup/freezer/virli/
ls /sys/fs/cgroup/freezer/virli/
```bash
mkdir /sys/fs/cgroup/freezer/virli/
ls /sys/fs/cgroup/freezer/virli/
```
</div>
@ -64,8 +64,8 @@ La liste des processus rattachés à un *cgroup* se trouve dans le fichier `task
du groupe. Pour ajouter une tâche à ce groupe, cela se passe de cette manière :
<div lang="en-US">
```
echo $PID > /sys/fs/cgroup/freezer/virli/tasks
```bash
echo $PID > /sys/fs/cgroup/freezer/virli/tasks
```
</div>
@ -102,8 +102,8 @@ Faisons exécuter à notre interpréteur une commande pour voir effectivement
l'exécution s'arrêter. Si vous manquez d'inspiration, utilisez :
<div lang="en-US">
```
for i in $(seq 9999); do echo -n $i; sleep .1; echo -n " - "; sleep .1; done
```bash
for i in $(seq 9999); do echo -n $i; sleep .1; echo -n " - "; sleep .1; done
```
</div>
@ -111,8 +111,8 @@ Maintenant, nous avons donné l'ordre au noyau de ne plus allouer de temps de
calcul à notre shell et ses fils :
<div lang="en-US">
```
echo FROZEN > /sys/fs/cgroup/freezer/virli/freezer.state
```bash
echo FROZEN > /sys/fs/cgroup/freezer/virli/freezer.state
```
</div>
@ -120,8 +120,8 @@ calcul à notre shell et ses fils :
l'exécution :
<div lang="en-US">
```
echo THAWED > /sys/fs/cgroup/freezer/virli/freezer.state
```bash
echo THAWED > /sys/fs/cgroup/freezer/virli/freezer.state
```
</div>
@ -138,8 +138,8 @@ Commençons par lancer le conteneur Docker d'InfluxDB (pour éviter de
l'installer sur notre machine) :
<div lang="en-US">
```shell
docker container run --name mytsdb -d -p 8086:8086 influxdb
```bash
docker container run --name mytsdb -d -p 8086:8086 influxdb
```
</div>
@ -148,11 +148,11 @@ métriques. Voici comment on s'était débrouillé dans un précédent TP pour
interagir avec InfluxDB :
<div lang="en-US">
```shell
docker container exec -i mytsdb influxdb <<EOF
CREATE DATABASE metrics;
SHOW DATABASES;
EOF
```bash
docker container exec -i mytsdb influxdb <<EOF
CREATE DATABASE metrics;
SHOW DATABASES;
EOF
```
</div>
@ -167,19 +167,21 @@ mémoire utilisée par le groupe monitoré.
Vous pouvez utiliser un programme comme `memhog` pour remplir rapidement votre
mémoire.
<div lang="en-US">
```
42sh# mkdir /sys/fs/cgroup...
42sh$ echo $$ | sudo tee /sys/fs/cgroup.../tasks
42sh# ./monitor group_name memhog 500
~~~ 13595 ~~~ Current memory usage: 75194368/550502400 (13%)
~~~ 13595 ~~~ Current memory usage: 150290432/550502400 (27%)
~~~ 13595 ~~~ Current memory usage: 223690752/550502400 (40%)
~~~ 13595 ~~~ Current memory usage: 296828928/550502400 (53%)
~~~ 13595 ~~~ Current memory usage: 368001024/550502400 (66%)
~~~ 13595 ~~~ Current memory usage: 438517760/550502400 (79%)
~~~ 13595 ~~~ Current memory usage: 480329728/550502400 (87%)
~~~ 13595 ~~~ Current memory usage: 155648/550502400 (0%)
42sh# mkdir /sys/fs/cgroup...
42sh$ echo $$ | sudo tee /sys/fs/cgroup.../tasks
42sh# ./monitor group_name memhog 500
~~~ 13595 ~~~ Current memory usage: 75194368/550502400 (13%)
~~~ 13595 ~~~ Current memory usage: 150290432/550502400 (27%)
~~~ 13595 ~~~ Current memory usage: 223690752/550502400 (40%)
~~~ 13595 ~~~ Current memory usage: 296828928/550502400 (53%)
~~~ 13595 ~~~ Current memory usage: 368001024/550502400 (66%)
~~~ 13595 ~~~ Current memory usage: 438517760/550502400 (79%)
~~~ 13595 ~~~ Current memory usage: 480329728/550502400 (87%)
~~~ 13595 ~~~ Current memory usage: 155648/550502400 (0%)
```
</div>
Si vous n'avez pas le *cgroup* *memory*, il est possible qu'il ne soit pas
activé par défaut par votre système. Si vous êtes dans ce cas, essayez
@ -192,9 +194,9 @@ Maintenant, envoyons nos données vers la base
<https://docs.influxdata.com/influxdb/v1.6/guides/writing_data/> :
<div lang="en-US">
```
curl -i -XPOST 'http://localhost:8086/write?db=metrics' --data-binary \
"$my_cgroup_name memory.usage_in_bytes=$(cat .../my_cgroup_name/memory.usage_in_bytes)"
```bash
curl -i -XPOST 'http://localhost:8086/write?db=metrics' --data-binary \
"$my_cgroup_name memory.usage_in_bytes=$(cat .../my_cgroup_name/memory.usage_in_bytes)"
```
</div>
@ -203,7 +205,7 @@ requête suivante dans notre client `influx` :
<div lang="en-US">
```sql
SELECT * from "$my_cgroup_name";
SELECT * from "$my_cgroup_name";
```
</div>
@ -235,8 +237,8 @@ particuliers.
<div lang="en-US">
```
42sh$ sudo ./monitor_init my_cgroup_name
42sh$ ./monitor my_cgroup_name memhog 500
42sh$ sudo ./monitor_init my_cgroup_name
42sh$ ./monitor my_cgroup_name memhog 500
```
</div>
@ -251,22 +253,24 @@ correspondant à une valeur limite, comme par exemple
`memory.max_usage_in_bytes`, qui limite le nombre d'octets que notre groupe de
processus va pouvoir allouer au maximum :
```shell
42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes
0
# 0 = Aucune limite
42sh$ echo 4M > /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes
# Maintenant, la limite est à 4MB, vérifions...
42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes
4194304
<div lang="en-US">
```
42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes
0
# 0 = Aucune limite
42sh$ echo 4M > /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes
# Maintenant, la limite est à 4MB, vérifions...
42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes
4194304
```
</div>
Chaque *cgroup*s défini de nombreux indicateurs et possède de nombreux
limiteurs, n'hésitez pas à consulter la documentation associée à chaque
*cgroup*.
## 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
Control groups](https://lwn.net/Articles/604609/) est excellente !

View file

@ -15,8 +15,8 @@ Pour se créer un environnement afin de changer notre racine, il va falloir
commencer par créer le dossier de notre nouvelle racine :
<div lang="en-US">
```shell
mkdir newroot
```bash
mkdir newroot
```
</div>
@ -26,12 +26,12 @@ Queques mots, pour commencer, à propos du projet Busybox : c'est un programme
*linké* statiquement, c'est-à-dire qu'il ne va pas chercher ni charger de
bibliothèque dynamique à son lancement. Il se suffit donc à lui-même dans un
*chroot*, car il n'a pas de dépendances. Nous pouvons donc tester notre
première isolation :
première isolation\ :
<div lang="en-US">
```shell
cp $(which busybox) newroot/
chroot newroot /busybox ash
```bash
cp $(which busybox) newroot/
chroot newroot /busybox ash
```
</div>
@ -39,10 +39,10 @@ Jusque là ... ça fonctionne, rien de surprenant ! Mais qu'en est-il pour
`bash` :
<div lang="en-US">
```shell
42sh$ cp $(which bash) newroot/
42sh# chroot newroot /bash
chroot: failed to run command bash: No such file or directory
```bash
42sh$ cp $(which bash) newroot/
42sh# chroot newroot /bash
chroot: failed to run command bash: No such file or directory
```
</div>
@ -57,8 +57,8 @@ dossier correspond au point de montage de la nouvelle racine choisie par
l'utilisateur lors de l'installation) le système de base.
<div lang="en-US">
```shell
debootstrap jessie newroot/ http://httpredir.debian.org/debian/
```bash
debootstrap jessie newroot/ http://httpredir.debian.org/debian/
```
</div>
@ -68,12 +68,12 @@ l'utilisateur lors de l'installation) le système de base.
### *stage3*
Les distributions *à l'ancienne* proposent encore de télécharger leur système
de base sous forme de tarball :
de base sous forme de tarball\ :
<div lang="en-US">
```shell
wget http://gentoo.mirrors.ovh.net/gentoo-distfiles/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20181021T214502Z.tar.xz
tar xpf stage3-amd64-*.tar.xz -C newroot/
```bash
wget http://gentoo.mirrors.ovh.net/gentoo-distfiles/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20181021T214502Z.tar.xz
tar xpf stage3-amd64-*.tar.xz -C newroot/
```
</div>
@ -81,31 +81,31 @@ L'avantage de télécharger l'archive de Gentoo est que l'on a déjà `gcc` dans
environnement qui tient dans 300 MB.
## Exercice
## Exercice {-}
Écrivons maintenant un programme dont le seul but est de s'échapper du `chroot`:
Écrivons maintenant un programme dont le seul but est de s'échapper du `chroot` :
<div lang="en-US">
```shell
make escape
echo bar > ../foo
chroot .
```bash
make escape
echo bar > ../foo
chroot .
```
</div>
Dans le nouvel environnement, vous ne devriez pas pouvoir faire :
<div lang="en-US">
```shell
cat ../foo
```bash
cat ../foo
```
</div>
Mais une fois votre programme `escape` exécuté, vous devriez pouvoir !
<div lang="en-US">
```shell
./escape
cat /path/to/foo
```
(chroot) 42sh# ./escape
bash# cat /path/to/foo
```
</div>

View file

@ -45,8 +45,8 @@ disponibles sur la page d'accueil de <https://kernel.org>.
Dans les sources, on affiche la liste des options avec la commande :
<div lang="en-US">
```shell
make menuconfig
```bash
make menuconfig
```
</div>

View file

@ -24,13 +24,13 @@ pour chaque exercice) :
<div lang="en-US">
```
login_x-TP3/escape.c
login_x-TP3/procinfo.sh
login_x-TP3/rev_kdb_leds.sh
login_x-TP3/view_caps.c
login_x-TP3/monitor.sh
login_x-TP3/monitor_init.sh
login_x-TP3/syscall_filter.c
login_x-TP3/escape.c
login_x-TP3/procinfo.sh
login_x-TP3/rev_kdb_leds.sh
login_x-TP3/view_caps.c
login_x-TP3/monitor.sh
login_x-TP3/monitor_init.sh
login_x-TP3/syscall_filter.c
```
</div>

View file

@ -16,8 +16,8 @@ montage :
<div lang="en-US">
```
/dev/sda1 on / type ext4 (rw,relatime,data=ordered)
/dev/sda3 on /home type ext4 (rw,relatime,data=ordered)
/dev/sda1 on / type ext4 (rw,relatime,data=ordered)
/dev/sda3 on /home type ext4 (rw,relatime,data=ordered)
```
</div>
@ -61,16 +61,20 @@ exemple, pour modifier les paramètres du noyau, on passe par le fichier
La consultation d'un élément se fait généralement à l'aide d'un simple `cat` :
```shell
42sh$ cat /sys/power/state
freeze mem
<div lang="en-US">
```
42sh$ cat /sys/power/state
freeze mem
```
</div>
La modification d'un élément se fait avec `echo`, comme ceci :
```shell
42sh# echo mem > /sys/power/state
<div lang="en-US">
```bash
42sh# echo mem > /sys/power/state
```
</div>
Vous devriez constater l'effet de cette commande sans plus attendre !
@ -84,39 +88,39 @@ afficher des informations sur un processus donné :
<div lang="en-US">
```
42sh$ ./procinfo $$
PID: 4242
Path: /bin/bash
Command line: bash
Working directory: /home/nemunaire/virli/
Root: /
State: S (sleeping)
Threads: 1
42sh$ ./procinfo $$
PID: 4242
Path: /bin/bash
Command line: bash
Working directory: /home/nemunaire/virli/
Root: /
State: S (sleeping)
Threads: 1
CGroups
=======
12:pids:/
11:net_prio:/
10:perf_event:/
9:net_cls:/
8:freezer:/
7:devices:/
6:memory:/
5:blkio:/
4:cpuacct:/
3:cpu:/
2:cpuset:/
1:name=openrc:/
CGroups
=======
12:pids:/
11:net_prio:/
10:perf_event:/
9:net_cls:/
8:freezer:/
7:devices:/
6:memory:/
5:blkio:/
4:cpuacct:/
3:cpu:/
2:cpuset:/
1:name=openrc:/
Namespaces
==========
cgroup:[4026531835]
ipc:[4026531839]
mnt:[4026531840]
net:[4026531969]
pid:[4026531836]
user:[4026531837]
uts:[4026531838]
Namespaces
==========
cgroup:[4026531835]
ipc:[4026531839]
mnt:[4026531840]
net:[4026531969]
pid:[4026531836]
user:[4026531837]
uts:[4026531838]
```
</div>
@ -147,8 +151,8 @@ Après avoir exécuté le script, nous devrions avoir :
Voici un exemple d'utilisation :
<div lang="en-US">
```shell
42sh$ ./rev_kdb_leds.sh input20
```
42sh$ ./rev_kdb_leds.sh input20
```
</div>
@ -158,23 +162,23 @@ Voici un exemple d'utilisation :
Voici un exemple d'utilisation :
<div lang="en-US">
```shell
42sh$ ./batinfo.sh
BAT0 Discharging
====
Capacity: 83% (Normal)
Voltage: 11.972000 V (minimal: 11.400000 V)
Energy: 18.290000/21.830000 Wh
Power: 7.937000 W
Remaining time: 2.304 h
```
42sh$ ./batinfo.sh
BAT0 Discharging
====
Capacity: 83% (Normal)
Voltage: 11.972000 V (minimal: 11.400000 V)
Energy: 18.290000/21.830000 Wh
Power: 7.937000 W
Remaining time: 2.304 h
BAT1 Unknown
====
Capacity: 83% (Normal)
Voltage: 11.972000 V (minimal: 11.400000 V)
Energy: 18.290000/21.830000 Wh
Power: 0.0 W
Remaining time: N/A
BAT1 Unknown
====
Capacity: 83% (Normal)
Voltage: 11.972000 V (minimal: 11.400000 V)
Energy: 18.290000/21.830000 Wh
Power: 0.0 W
Remaining time: N/A
```
</div>
@ -184,21 +188,21 @@ Voici un exemple d'utilisation :
Voici un exemple d'utilisation :
<div lang="en-US">
```shell
42sh$ ./cpuinfo.sh
cpu0
====
Current frequency: 2100384 Hz
Current governor: powersave
Allowed frequencies: between 500000 - 2100000 Hz
Thermal throttle count: 0
```
42sh$ ./cpuinfo.sh
cpu0
====
Current frequency: 2100384 Hz
Current governor: powersave
Allowed frequencies: between 500000 - 2100000 Hz
Thermal throttle count: 0
cpu1
====
Current frequency: 2099871 Hz
Current governor: powersave
Allowed frequencies: between 500000 - 2100000 Hz
Thermal throttle count: 0
cpu1
====
Current frequency: 2099871 Hz
Current governor: powersave
Allowed frequencies: between 500000 - 2100000 Hz
Thermal throttle count: 0
```
</div>

View file

@ -43,7 +43,7 @@ ce mode via :
<div lang="en-US">
```c
prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
```
</div>
@ -67,25 +67,25 @@ argument de l'appel système :
<div lang="en-US">
```c
struct sock_filter filter[];
struct sock_fprog prog = {
.len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};
seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
struct sock_filter filter[];
struct sock_fprog prog = {
.len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};
seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
```
</div>
### Exercice
### Exercice {-}
Écrivez un programme filtrant un appel système, à l'aide de `seccomp` :
<div lang="en-US">
```
42sh$ ./syscall_filter sleep 5
sleep: cannot read realtime clock: Operation not permitted
42sh$
42sh$ ./syscall_filter sleep 5
sleep: cannot read realtime clock: Operation not permitted
42sh$
```
</div>

View file

@ -1,22 +1,25 @@
---
title: Virtualisation légère -- TP n^o^ 3
subtitle: Linux Internals partie 1
author: Pierre-Olivier *Nemunaire* Mercier
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA
date: Mercredi 24 octobre 2018
abstract: |
Ce premier TP consacré aux Linux Internals va nous permettre
d'appréhender les notions de pseudos systèmes de fichiers, de
cgroups ainsi que de capabilities.
\vspace{1em}
Certains éléments de ce TP sont à rendre à <virli@nemunai.re> au
plus tard le mercredi 7 novembre 2018 à 12 h 42. Consultez la
dernière section de chaque partie pour plus d'information sur les
éléments à rendre.
En tant que personnes sensibilisées à la sécurité des échanges
électroniques, vous devrez m'envoyer vos rendus signés avec votre
clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96)
faire signer votre clef et n'hésitez pas à [faire signer votre
clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
...
Ce premier TP consacré aux Linux Internals va nous permettre d'appréhender les
notions de pseudos systèmes de fichiers, de cgroups ainsi que de capabilities.
Certains éléments de ce TP sont à rendre à <virli@nemunai.re> au plus tard le
mercredi 7 novembre 2018 à 12 h 42. Consultez la dernière section de chaque partie
pour plus d'information sur les éléments à rendre.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
[faire signer votre clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
\tableofcontents

View file

@ -1,22 +1,8 @@
include ../pandoc-opts.mk
SOURCES_TUTO = tutorial.md setup.md cmpns.md docker-exec.md mountns.md rendu.md
SOURCES_LESSON = lesson.md mount.md namespaces.md networkns.md pidns.md userns.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=fr-FR \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
-M colorlinks=true \
-M linkcolor="black" \
-M urlcolor="[rgb]{0.2,0.6,0.4}" \
--include-in-header=../header.tex
all: lesson.pdf tutorial.pdf

View file

@ -17,7 +17,7 @@ Exemples {.unnumbered}
--------
<div lang="en-US">
```sh
```
42sh$ ./cmpns $(pgrep influxdb) $(pgrep init)
- cgroup: differ
- ipc: differ
@ -30,7 +30,7 @@ Exemples {.unnumbered}
</div>
<div lang="en-US">
```sh
```
42sh$ ./cmpns $(pgrep init) self
- cgroup: same
- ipc: same
@ -47,7 +47,7 @@ Ici, `self` fait référence au processus actuellement exécuté.
Et pourquoi pas :
<div lang="en-US">
```sh
```
42sh$ unshare -m ./cmpns $$ self
- cgroup: same
- ipc: same

View file

@ -17,33 +17,33 @@ Pour savoir si vous avez réussi, comparez les sorties des commandes :
- ...
Tests {.unnumbered}
Tests {-}
-----
<div lang="en-US">
```shell
42sh$ docker run --name mywebserver -d -p 80:80 nginx
d63ceae863956f8312aca60b7a57fbcc1fdf679ae4c90c5d9455405005d4980a
42sh$ docker container inspect --format '{{ .State.Pid }}' mywebserver
234269
```
42sh$ docker run --name mywebserver -d -p 80:80 nginx
d63ceae863956f8312aca60b7a57fbcc1fdf679ae4c90c5d9455405005d4980a
42sh$ docker container inspect --format '{{ .State.Pid }}' mywebserver
234269
42sh# ./mydocker_exec mywebserver ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
42sh# ./mydocker_exec mywebserver ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
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
valid_lft forever preferred_lft forever
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
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
valid_lft forever preferred_lft forever
42sh# hostname
koala.zoo.paris
42sh# ./mydocker_exec mywebserver hostname
d63ceae86395
42sh# hostname
koala.zoo.paris
42sh# ./mydocker_exec mywebserver hostname
d63ceae86395
42sh# ./mydocker_exec mywebserver mount
42sh# ./mydocker_exec mywebserver ps aux
...
42sh# ./mydocker_exec mywebserver mount
42sh# ./mydocker_exec mywebserver ps aux
...
```
</div>

View file

@ -1,14 +1,12 @@
---
title: Virtualisation légère -- Linux Internals partie 2
subtitle: Support de cours
author: Pierre-Olivier *nemunaire* Mercier
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA
date: Mercredi 7 novembre 2018
abstract: |
Le but de cette seconde partie sur les mécanismes internes du noyau
va nous permettre d'utiliser les commandes et les appels systèmes
relatifs aux espaces de noms du noyau Linux ainsi que d'appréhender
la complexité des sytèmes de fichiers.
...
Le but de cette seconde partie sur les mécanismes internes du noyau va nous
permettre d'utiliser les commandes et les appels systèmes relatifs aux espaces
de noms du noyau Linux ainsi que d'appréhender la complexité des sytèmes de
fichiers.
\tableofcontents

View file

@ -63,8 +63,8 @@ Lorsque l'on souhaite monter à un deuxième endroit (ou plus) une partition, on
utilise le *bind mount* :
<div lang="en-US">
```
mount --bind olddir newdir
```bash
mount --bind olddir newdir
```
</div>
@ -81,11 +81,11 @@ Pour que tout cela fonctionne, nous aurons besoin, au préalable, d'exécuter le
commandes suivantes :
<div lang="en-US">
```
cd newroot
mount --bind /dev dev
mount --bind /proc proc
mount --bind /sys sys
```bash
cd newroot
mount --bind /dev dev
mount --bind /proc proc
mount --bind /sys sys
```
</div>
@ -104,11 +104,11 @@ d'accroche qu'il contient, il faut utiliser `--rbind`. Il serait donc plus
correct de lancer :
<div lang="en-US">
```
cd newroot
mount --rbind /dev dev
mount -t proc none proc
mount --rbind /sys sys
```bash
cd newroot
mount --rbind /dev dev
mount -t proc none proc
mount --rbind /sys sys
```
</div>
@ -128,15 +128,15 @@ Dans un montage partagé, une nouvelle accroche sera propagée parmi tous les
systèmes de fichiers de ce partage (on parle de *peer group*).
<div lang="en-US">
```shell
# Création de notre répertoire de travail
mkdir /mnt/test-shared
```bash
# Création de notre répertoire de travail
mkdir /mnt/test-shared
# On s'assure que le dossier que l'on va utiliser pour nos tests utilise bien la politique shared
mount --make-shared /tmp
# On s'assure que le dossier que l'on va utiliser pour nos tests utilise bien la politique shared
mount --make-shared /tmp
# Duplication de l'accroche, sans s'occuper des éventuels sous-accroches
mount --bind /tmp /mnt/test-shared
# Duplication de l'accroche, sans s'occuper des éventuels sous-accroches
mount --bind /tmp /mnt/test-shared
```
</div>
@ -144,9 +144,9 @@ Si l'on attache un nouveau point de montage dans `/tmp` ou dans
`/mnt/test-shared`, avec la politique `shared`, l'accroche sera propagée :
<div lang="en-US">
```shell
mkdir /mnt/test-shared/toto
mount -t tmpfs none /mnt/test-shared/toto
```bash
mkdir /mnt/test-shared/toto
mount -t tmpfs none /mnt/test-shared/toto
```
</div>
@ -161,33 +161,33 @@ propagera, mais seulement dans un sens. Le point de montage déclaré comme
esclave ne propagera pas ses nouveaux points de montage à son *maître*.
<div lang="en-US">
```shell
# Suite de l'exemple précédent
cd /mnt/test-slave
```bash
# Suite de l'exemple précédent
cd /mnt/test-slave
# Duplication de l'accroche, sans s'occuper des éventuels sous-accroches
mount --bind /mnt/test-shared /mnt/test-slave
# Duplication de l'accroche, sans s'occuper des éventuels sous-accroches
mount --bind /mnt/test-shared /mnt/test-slave
# On rend notre dossier esclave
mount --make-slave /mnt/test-slave
# On rend notre dossier esclave
mount --make-slave /mnt/test-slave
```
</div>
Si l'on effectue un montage dans `/mnt/test-shared` :
<div lang="en-US">
```shell
mkdir /mnt/test-shared/foo
mount -t tmpfs none /mnt/test-shared/foo
```bash
mkdir /mnt/test-shared/foo
mount -t tmpfs none /mnt/test-shared/foo
```
</div>
Le point de montage apparaît bien sous `/mnt/test-slave/foo`. Par contre :
<div lang="en-US">
```shell
mkdir /mnt/test-slave/bar
mount -t tmpfs none /mnt/test-slave/bar
```bash
mkdir /mnt/test-slave/bar
mount -t tmpfs none /mnt/test-slave/bar
```
</div>
@ -203,8 +203,8 @@ Pour forcer un point d'accroche à ne pas propager et à ne pas recevoir de
propagation, on utilise l'option suivante :
<div lang="en-US">
```shell
mount --make-private mountpoint
```bash
mount --make-private mountpoint
```
</div>
@ -214,17 +214,17 @@ propagation, on utilise l'option suivante :
Ce mode interdira tout tentative d'attache à un autre endroit.
<div lang="en-US">
```shell
mount --make-unbindable /mnt/test-slave
```bash
mount --make-unbindable /mnt/test-slave
```
</div>
Il ne sera pas possible de faire :
<div lang="en-US">
```shell
mkdir /mnt/test-unbindable
mount --bind /mnt/test-slave /mnt/test-unbindable
```bash
mkdir /mnt/test-unbindable
mount --bind /mnt/test-slave /mnt/test-unbindable
```
</div>
@ -236,11 +236,11 @@ existe les mêmes options pour les appliquer en cascade sur les points d'attache
contenus dans leur sous-arbre :
<div lang="en-US">
```
mount --make-rshared mountpoint
mount --make-rslave mountpoint
mount --make-rprivate mountpoint
mount --make-runbindable mountpoint
```bash
mount --make-rshared mountpoint
mount --make-rslave mountpoint
mount --make-rprivate mountpoint
mount --make-runbindable mountpoint
```
</div>
@ -269,16 +269,16 @@ emplacement soient prévenu du changement.
On utilise pour cela l'option `--move` de `mount(8)` :
<div lang="en-US">
```shell
mount --move olddir newdir
```bash
mount --move olddir newdir
```
</div>
Par exemple :
<div lang="en-US">
```shell
mount --move /dev /newroot/dev
```bash
mount --move /dev /newroot/dev
```
</div>
@ -287,7 +287,7 @@ racine de notre système de fichiers : par exemple pour passer de l'*initramfs*
au système démarré, de notre système hôte au système d'un conteneur, ...
## Aller plus loin
## Aller plus loin {-}
Voici quelques articles qui valent le détour, en lien avec les points de
montage :

View file

@ -17,7 +17,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
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
l'arborescence !
l'arborescence\ !
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
@ -39,9 +39,9 @@ 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` :
<div lang="en-US">
```shell
42sh# mkdir /mnt/newroot
42sh# mount -t tmpfs none /mnt/newroot
```bash
42sh# mkdir /mnt/newroot
42sh# mount -t tmpfs none /mnt/newroot
```
</div>
@ -73,8 +73,8 @@ devoir nous isoler sur :
Isolons-nous :
<div lang="en-US">
```shell
42sh# unshare -p -m -f --mount-proc
```bash
42sh# unshare -p -m -f --mount-proc
```
</div>
@ -89,8 +89,8 @@ Commençons donc par étiqueter tous nos points de montage (de ce *namespace*),
comme esclave :
<div lang="en-US">
```shell
42sh# mount --make-rslave /
```bash
42sh# mount --make-rslave /
```
</div>
@ -131,7 +131,7 @@ Pour lancer la première commande dans la nouvelle racine, on passe généraleme
par :
<div lang="en-US">
```shell
42sh# exec chroot / command
```bash
42sh# exec chroot / command
```
</div>

View file

@ -44,9 +44,11 @@ notre *namespace* est d'appliquer le type esclave à l'ensemble de nos points de
montage, récursivement, dès que l'on est entré dans notre nouvel espace de
noms.
```shell
mount --make-rslave /
<div lang="en-US">
```bash
mount --make-rslave /
```
</div>
### L'espace de noms `UTS` {#uts-ns}
@ -148,18 +150,18 @@ Par exemple, nous pouvons modifier sans crainte le nom de notre machine, si
nous sommes passés dans un autre *namespace* `UTS` :
<div lang="en-US">
```shell
42sh# hostname --fqdn
koala.zoo.paris
42sh# sudo unshare -u /bin/bash
bash# hostname --fqdn
koala.zoo.paris
bash# hostname lynx.zoo.paris
bash# hostname --fqdn
lynx.zoo.paris
bash# exit
42sh# hostname --fqdn
koala.zoo.paris
```
42sh# hostname --fqdn
koala.zoo.paris
42sh# sudo unshare -u /bin/bash
bash# hostname --fqdn
koala.zoo.paris
bash# hostname lynx.zoo.paris
bash# hostname --fqdn
lynx.zoo.paris
bash# exit
42sh# hostname --fqdn
koala.zoo.paris
```
</div>
@ -194,17 +196,17 @@ similaire à :
<div lang="en-US">
```c
#include <sched.h>
#include <sched.h>
#define STACKSIZE (1024*1024)
static char child_stack[STACKSIZE];
#define STACKSIZE (1024*1024)
static char child_stack[STACKSIZE];
int clone_flags = CLONE_CGROUP | CLONE_NEWNET | SIGCHLD;
int clone_flags = CLONE_CGROUP | CLONE_NEWNET | SIGCHLD;
pid_t pid = clone(do_execvp,
child_stack + STACKSIZE,
clone_flags,
&args);
pid_t pid = clone(do_execvp,
child_stack + STACKSIZE,
clone_flags,
&args);
```
</div>
@ -220,41 +222,41 @@ auquel on passe le *file descriptor* d'un des liens du dossier
<div lang="en-US">
```c
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <stdlib.h>
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <stdlib.h>
// ./a.out /proc/PID/ns/FILE cmd args...
// ./a.out /proc/PID/ns/FILE cmd args...
int main(int argc, char *argv[])
{
int fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("open");
return EXIT_FAILURE;
}
if (setns(fd, 0) == -1)
{
perror("setns");
return EXIT_FAILURE;
}
execvp(argv[2], &argv[2]);
perror("execve");
int main(int argc, char *argv[])
{
int fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("open");
return EXIT_FAILURE;
}
}
if (setns(fd, 0) == -1)
{
perror("setns");
return EXIT_FAILURE;
}
execvp(argv[2], &argv[2]);
perror("execve");
return EXIT_FAILURE;
}
```
</div>
Dans un shell, on utilisera la commande `nsenter(1)` :
<div lang="en-US">
```shell
42sh# nsenter --uts=/proc/42/ns/uts /bin/bash
```bash
42sh# nsenter --uts=/proc/42/ns/uts /bin/bash
```
</div>
@ -275,9 +277,9 @@ 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` :
<div lang="en-US">
```shell
42sh# touch /tmp/ns/myrefns
42sh# mount --bind /proc/<PID>/ns/mount /tmp/ns/myrefns
```bash
42sh# touch /tmp/ns/myrefns
42sh# mount --bind /proc/<PID>/ns/mount /tmp/ns/myrefns
```
</div>
@ -296,7 +298,7 @@ Même en étant attaché à un fichier du disque, il s'agit d'un pointeur vers u
structure du noyau, qui ne persistera pas au redémarrage.
## Aller plus loin
## Aller plus loin {-}
Je vous recommande la lecture des *man* suivants :

View file

@ -13,10 +13,10 @@ En entrant dans un nouvel espace de nom `network`, on se retrouve dans un
environnement qui n'a plus qu'une interface de *loopback* :
<div lang="en-US">
```shell
42sh# unshare -n ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
```
42sh# unshare -n ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
```
</div>
@ -38,8 +38,8 @@ La suite d'outils `iproute2` propose une interface simplifiée pour utiliser le
Nous pouvons tout d'abord créer un nouvel espace de nom :
<div lang="en-US">
```shell
42sh# ip netns add virli
```bash
42sh# ip netns add virli
```
</div>
@ -53,10 +53,10 @@ Maintenant que notre *namespace* est créé, nous pouvons regarder s'il contient
des interfaces :
<div lang="en-US">
```sh
42sh# ip netns exec virli ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
```
42sh# ip netns exec virli ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
```
</div>
@ -67,19 +67,19 @@ D'ailleurs, cette interface est rapportée comme étant désactivée, activons-l
via la commande :
<div lang="en-US">
```shell
42sh# ip netns exec virli ip link set dev lo up
```bash
42sh# ip netns exec virli ip link set dev lo up
```
</div>
À ce stade, nous pouvons déjà commencer à lancer un `ping` sur cette interface:
<div lang="en-US">
```shell
42sh# ip netns exec virli ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.038 ms
...
```
42sh# ip netns exec virli ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.038 ms
...
```
</div>
@ -96,7 +96,7 @@ type `veth` :
<div lang="en-US">
```
42sh# ip link add veth0 type veth peer name veth1
42sh# ip link add veth0 type veth peer name veth1
```
</div>
@ -112,17 +112,17 @@ devient alors possible de réaliser un échange de paquets entre les deux.
Pour déplacer `veth1` dans notre *namespace* `virli` :
<div lang="en-US">
```shell
42sh# ip link set veth1 netns virli
```bash
42sh# ip link set veth1 netns virli
```
</div>
Il ne reste maintenant plus qu'à assigner une IP à chacune des interfaces :
<div lang="en-US">
```shell
42sh# ip netns exec virli ip a add 10.10.10.42/24 dev veth1
42sh# ip a add 10.10.10.41/24 dev veth0
```bash
42sh# ip netns exec virli ip a add 10.10.10.42/24 dev veth1
42sh# ip a add 10.10.10.41/24 dev veth0
```
</div>
@ -132,10 +132,10 @@ Dès lors[^linkdown], nous pouvons `ping`er chaque extrêmité :
vethX up`.
<div lang="en-US">
```shell
42sh# ping 10.10.10.42
- et -
42sh# ip netns exec virli ping 10.10.10.41
```
42sh# ping 10.10.10.42
- et -
42sh# ip netns exec virli ping 10.10.10.41
```
</div>
@ -158,9 +158,9 @@ supportant la technologie [802.1q](https://fr.wikipedia.org/wiki/IEEE_802.1Q).
<div lang="en-US">
```
42sh# ip link add link eth0 name eth0.100 type vlan id 100
42sh# ip link set dev eth0.100 up
42sh# ip link set eth0.100 netns virli
42sh# ip link add link eth0 name eth0.100 type vlan id 100
42sh# ip link set dev eth0.100 up
42sh# ip link set eth0.100 netns virli
```
</div>
@ -192,7 +192,7 @@ Pour construire une nouvelle interface de ce type :
<div lang="en-US">
```
42sh# ip link add link eth0 mac0 type macvlan mode vepa
42sh# ip link add link eth0 mac0 type macvlan mode vepa
```
</div>
@ -208,7 +208,7 @@ conteneur de la même machine.
<div lang="en-US">
```
42sh# ip link add link eth0 mac1 type macvlan mode private
42sh# ip link add link eth0 mac1 type macvlan mode private
```
</div>
@ -224,12 +224,12 @@ Pour construire une nouvelle interface de ce type :
<div lang="en-US">
```
42sh# ip link add link eth0 mac2 type macvlan mode bridge
42sh# ip link add link eth0 mac2 type macvlan mode bridge
```
</div>
## Aller plus loin
## Aller plus loin {-}
Pour approfondir les différentes techniques de routage, je vous
recommande cet article :

View file

@ -23,8 +23,8 @@ trouve.
Première étape s'isoler :
<div lang="en-US">
```shell
42sh# unshare --pid --fork /bin/bash
```bash
42sh# unshare --pid --fork /bin/bash
```
</div>
@ -50,8 +50,8 @@ notre système initial. Pour s'en sortir, il est nécessaire de s'isoler du
Voici la nouvelle ligne de commande que l'on va utiliser :
<div lang="en-US">
```shell
42sh# unshare --pid --mount --fork --mount-proc /bin/bash
```bash
42sh# unshare --pid --mount --fork --mount-proc /bin/bash
```
</div>
@ -94,7 +94,7 @@ l'extérieur du conteneur, les propriétés d'`init` sont biens appliquées à
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é à cet espace de
noms : `pid_namespaces(7)`.

View file

@ -26,7 +26,7 @@ Voici une arborescence type:
<div lang="en-US">
```
login_x-mymoulette/README
login_x-mymoulette/...
login_x-mymoulette/README
login_x-mymoulette/...
```
</div>

View file

@ -37,8 +37,8 @@ Voici une arborescence type :
<div lang="en-US">
```
login_x-TP4/cmpns.sh
login_x-TP4/mydocker_exec.sh
login_x-TP4/myswitch_root.sh
login_x-TP4/cmpns.sh
login_x-TP4/mydocker_exec.sh
login_x-TP4/myswitch_root.sh
```
</div>

View file

@ -94,9 +94,11 @@ noyau pour adapter le comportement.
Si vous utilisez Debian ou l'un de ses dérivés, vous devrez autoriser
explicitement cette utilisation non-privilégiée :
```shell
42sh# sysctl -w kernel.unprivileged_userns_clone=1
<div lang="en-US">
```bash
42sh# sysctl -w kernel.unprivileged_userns_clone=1
```
</div>
### Grsecurity {.unnumbered}

View file

@ -1,22 +1,24 @@
---
title: Virtualisation légère -- TP n^o^ 4
subtitle: Linux Internals partie 2
author: Pierre-Olivier *nemunaire* Mercier
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA
date: Mercredi 7 novembre 2018
abstract: |
Le but de ce second TP sur les mécanismes internes du noyau va nous
permettre d'utiliser les commandes et les appels systèmes relatifs
aux *namespaces* ainsi que d'appréhender la complexité des systèmes
de fichiers.
\vspace{1em}
Tous les exercices de ce TP sont à rendre à <virli@nemunai.re> au
plus tard le mercredi 14 novembre 2017 à 12 h 42.
En tant que personnes sensibilisées à la sécurité des échanges
électroniques, vous devrez m'envoyer vos rendus signés avec votre
clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96)
faire signer votre clef et n'hésitez pas à [faire signer votre
clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
...
Le but de ce second TP sur les mécanismes internes du noyau va nous permettre
d'utiliser les commandes et les appels systèmes relatifs aux *namespaces* ainsi
que d'appréhender la complexité des systèmes de fichiers.
Tous les exercices de ce TP sont à rendre à <virli@nemunai.re> au plus tard le
mercredi 14 novembre 2017 à 12 h 42.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
[faire signer votre clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
\tableofcontents

View file

@ -66,8 +66,8 @@ Par exemple, le *namespace* `user` initial défini la correspondance suivante :
<div lang="en-US">
```
42sh$ cat /proc/self/uid_map
0 0 4294967295
42sh$ cat /proc/self/uid_map
0 0 4294967295
```
</div>
@ -79,8 +79,8 @@ Lorsque l'on crée un *namespace* `user`, généralement, la correspondance vaut
<div lang="en-US">
```
42sh$ cat /proc/self/uid_map
0 1000 1
42sh$ cat /proc/self/uid_map
0 1000 1
```
</div>
@ -98,8 +98,8 @@ des groupes au lieu des utilisateurs.
## Utilisation de l'espace de noms
<div lang="en-US">
```shell
42sh$ unshare --mount --pid --mount-proc --fork --net --user --map-root-user /bin/bash
```bash
42sh$ unshare --mount --pid --mount-proc --fork --net --user --map-root-user /bin/bash
```
</div>
@ -110,7 +110,7 @@ jeu. L'idée étant que l'on a été désigné root dans son conteneur, on devra
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é à ce *namespace* :
`user_namespaces(7)`.

View file

@ -1,19 +1,6 @@
include ../pandoc-opts.mk
SOURCES = tutorial.md setup.md what.md manual.md compose.md security.md rendu.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=fr-FR \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
-M colorlinks=true \
-M linkcolor="black" \
-M urlcolor="[rgb]{0.2,0.6,0.4}" \
--include-in-header=../header.tex
all: tutorial.pdf

View file

@ -12,19 +12,19 @@ construction).
<div lang="en-US">
```yaml
version: '3'
services:
influxdb:
...
chronograf:
build: grafana/
image: nginx
ports:
- "3000:3000"
volumes:
- ./:/tmp/toto
links:
- influxdb
version: '3'
services:
influxdb:
...
chronograf:
build: grafana/
image: nginx
ports:
- "3000:3000"
volumes:
- ./:/tmp/toto
links:
- influxdb
```
</div>
@ -61,9 +61,9 @@ suit :
<div lang="en-US">
```yaml
volumes:
mysql-data:
driver: local
volumes:
mysql-data:
driver: local
```
</div>
@ -72,11 +72,11 @@ l'emplacement à partager :
<div lang="en-US">
```yaml
[...]
mysql:
[...]
mysql:
[...]
volumes:
- mysql-data:/var/lib/mysql
volumes:
- mysql-data:/var/lib/mysql
```
</div>
@ -94,9 +94,9 @@ qui pourront être utilisés par les `services`. On pourrait donc avoir :
<div lang="en-US">
```yaml
networks:
knotdns-slave-net:
driver: bridge
networks:
knotdns-slave-net:
driver: bridge
```
</div>
@ -145,8 +145,8 @@ Une fois le build terminé, nous pouvons lancer la commande suivante et admirer
le résultat :
<div lang="en-US">
```shell
docker-compose up
```bash
docker-compose up
```
</div>

View file

@ -26,7 +26,7 @@ allons tâcher d'utiliser ce même port pour tester localement :
<div lang="en-US">
```
docker container run -p 8086:8086 -d --name mytsdb influxdb
docker container run -p 8086:8086 -d --name mytsdb influxdb
```
</div>
@ -35,9 +35,9 @@ notre base de données en appelant :
<div lang="en-US">
```
42sh$ curl -f http://localhost:8086/ping
42sh$ echo $?
0
42sh$ curl -f http://localhost:8086/ping
42sh$ echo $?
0
```
</div>
@ -46,15 +46,15 @@ le client fourni :
<div lang="en-US">
```
42sh$ docker container run --rm -it --link mytsdb:influxdb \
--entrypoint "/usr/bin/influx" influxdb -host influxdb
Connected to http://influxdb:8086 version 1.6.3
InfluxDB shell version: 1.6.3
> show databases
name: databases
name
---------------
_internal
42sh$ docker container run --rm -it --link mytsdb:influxdb \
> --entrypoint "/usr/bin/influx" influxdb -host influxdb
Connected to http://influxdb:8086 version 1.6.3
InfluxDB shell version: 1.6.3
> show databases
name: databases
name
---------------
_internal
```
</div>
@ -67,7 +67,7 @@ faut utiliser la commande `docker container logs` :
<div lang="en-US">
```
docker container logs mytsdb
docker container logs mytsdb
```
</div>
@ -84,18 +84,18 @@ Tentons maintenant de remplir notre base de données avec les métriques du
système. Pour cela, on commence par télécharger *Telegraf* :
<div lang="en-US">
```shell
curl https://dl.influxdata.com/telegraf/releases/telegraf-1.8.1-static_linux_amd64.tar.gz | \
tar xzv -C /tmp
```bash
curl https://dl.influxdata.com/telegraf/releases/telegraf-1.8.1-static_linux_amd64.tar.gz | \
tar xzv -C /tmp
```
</div>
Puis, lançons *Telegraf* :
<div lang="en-US">
```shell
cd /tmp/telegraf
./telegraf --config telegraf.conf
```bash
cd /tmp/telegraf
./telegraf --config telegraf.conf
```
</div>
@ -107,32 +107,32 @@ rediriger le port de notre conteneur sur notre machine locale (option `-p`).
Et observons ensuite :
<div lang="en-US">
```shell
42sh$ docker container run --rm -it --link mytsdb:influxdb \
--entrypoint "/usr/bin/influx" influxdb -host influxdb
InfluxDB shell version: 1.6.3
> show databases
name: databases
name
---------------
_internal
telegraf
```bash
42sh$ docker container run --rm -it --link mytsdb:influxdb \
> --entrypoint "/usr/bin/influx" influxdb -host influxdb
InfluxDB shell version: 1.6.3
> show databases
name: databases
name
---------------
_internal
telegraf
> use telegraf
Using database telegraf
> use telegraf
Using database telegraf
> show measurements
name: measurements
name
------------------
cpu
disk
diskio
kernel
mem
processes
swap
system
> show measurements
name: measurements
name
------------------
cpu
disk
diskio
kernel
mem
processes
swap
system
```
</div>
@ -142,7 +142,7 @@ lancé, celui-ci va régulièrement envoyer des métriques de cette machine.
## Afficher les données collectées
\hspace{2em}**Exercice :** À vous de jouer pour lancer le conteneur
**Exercice :** À vous de jouer pour lancer le conteneur
[*Chronograf*](https://store.docker.com/images/chronograf).
L'interface de *Chronograf* est disponible sur le port 8888.
@ -150,10 +150,9 @@ L'interface de *Chronograf* est disponible sur le port 8888.
Consultez la [documentation du conteneur](https://hub.docker.com/_/chronograf)
si besoin.
*Attention :* la page d'accueil est vide au démarrage, pour savoir si vous avez
**Attention :** 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
apparaître. En cliquant dessus vous obtiendrez des graphiques similaires à ceux
ci-dessous :
![Résultat obtenu](chronograf_latest.png)

View file

@ -11,7 +11,7 @@ monitoring, d'un simple :
<div lang="en-US">
```
42sh$ docker-compose up
42sh$ docker-compose up
```
</div>
@ -50,10 +50,10 @@ cela dépendra de votre avancée dans le projet) :
<div lang="en-US">
```
login_x-TP2/
login_x-TP2/tick/
login_x-TP2/tick/docker-compose.yml
login_x-TP2/tick/...
login_x-TP2/
login_x-TP2/tick/
login_x-TP2/tick/docker-compose.yml
login_x-TP2/tick/...
```
</div>

View file

@ -104,8 +104,8 @@ On peut ensuite l'appliquer à un conteneur Docker :
<div lang="en-US">
```
42sh$ docker container run -it --security-opt seccomp=nanosleep.json ubuntu /bin/bash
(cntnr)$ sleep 42
sleep: cannot read realtime clock: Operation not permitted
42sh$ docker container run -it --security-opt seccomp=nanosleep.json ubuntu /bin/bash
(cntnr)$ sleep 42
sleep: cannot read realtime clock: Operation not permitted
```
</div>

View file

@ -32,10 +32,10 @@ L'équipe en charge de Docker compose met à disposition un exécutable contenan
tous les scripts. Nous pouvons l'installer en suivant la procédure suivante :
<div lang="en-US">
```shell
curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-Linux-x86_64 \
> /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose
```bash
curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-Linux-x86_64 \
> /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose
```
</div>
@ -53,8 +53,8 @@ Comme avec Docker, nous pouvons vérifier le bon fonctionnement de
<div lang="en-US">
```
42sh$ docker-compose --version
docker-compose version: 1.16.1
42sh$ docker-compose --version
docker-compose version: 1.16.1
```
</div>

View file

@ -1,22 +1,23 @@
---
title: Virtualisation légère -- TP n^o^ 2.2
subtitle: Aller plus loin avec Docker
author: Pierre-Olivier *Nemunaire* Mercier
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA
date: Jeudi 18 octobre 2017
abstract: |
Dans cette deuxième partie du TP, nous allons approfondir l'utilisation de
Docker !
\vspace{1em}
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le mercredi 24 octobre 2017 à 0
h 42. Consultez la dernière section de chaque partie pour plus d'information
sur les éléments à rendre.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96)
faire signer votre clef et n'hésitez pas à [faire signer votre
clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
...
Dans cette deuxième partie du TP, nous allons approfondir l'utilisation de Docker !
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le mercredi 24 octobre 2017 à 0 h 42. Consultez la
dernière section de chaque partie pour plus d'information sur les éléments à
rendre.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
[faire signer votre clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
\tableofcontents

View file

@ -1,19 +1,6 @@
include ../pandoc-opts.mk
SOURCES = tutorial.md installation.md what.md first.md cleaning.md ex-flask.md volumes.md linking.md rendu.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=fr-FR \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
-M colorlinks=true \
-M linkcolor="black" \
-M urlcolor="[rgb]{0.2,0.6,0.4}" \
--include-in-header=../header.tex
all: tutorial.pdf

View file

@ -21,10 +21,10 @@ cours d'exécution, arrêtés, ...) avec la commande suivante :
<div lang="en-US">
```
42sh$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
552d71619723 hello-world "/hello" 4 days ago Exited (0) 4 days ago dreamy_gates
0e8bbff6d500 debian "/bin/bash" 2 weeks ago Exited (0) 2 weeks ago cranky_jones
42sh$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
552d71619723 hello-world "/hello" 4 days ago Exited (0) 4 days ago dreamy_gates
0e8bbff6d500 debian "/bin/bash" 2 weeks ago Exited (0) 2 weeks ago cranky_jones
```
</div>
@ -32,16 +32,16 @@ Il y a de fortes chances pour que vous n'ayez plus besoin de ces vieux
conteneurs. Pour les supprimer, utilisez la commande :
<div lang="en-US">
```
docker container rm 0e8bbff6d500 552d71619723
```bash
docker container rm 0e8bbff6d500 552d71619723
```
</div>
ou encore :
<div lang="en-US">
```
docker container rm cranky_jones dreamy_gates
```bash
docker container rm cranky_jones dreamy_gates
```
</div>
@ -62,6 +62,6 @@ une commande `prune` qui supprimera les objets inutilisés.
## `docker-gc`
Vous pouvez également utiliser l'image <https://github.com/spotify/docker-gc>
pour effectuer le ménage de manière automatique, plus fréquemment. Mais
attention à vos données !
Vous pouvez également utiliser l'image
[https://github.com/spotify/docker-gc](`docker-gc`) pour effectuer le ménage de
manière automatique, plus fréquemment. Mais attention à vos données !

View file

@ -12,8 +12,8 @@ page : <https://you.p0m.fr/>.
Nous pouvons télécharger et lancer le service grâce à :
<div lang="en-US">
```
docker container run -i nemunaire/youp0m
```bash
docker container run -i nemunaire/youp0m
```
</div>
@ -35,8 +35,8 @@ interférer avec son hôte.
Nous pouvons rediriger le port avec l'argument <span lang="en-US">`-p dst_host:src_cntr`</span> :
<div lang="en-US">
```
docker container run -i -p 8080:8080 nemunaire/youp0m
```bash
docker container run -i -p 8080:8080 nemunaire/youp0m
```
</div>
@ -46,19 +46,19 @@ Pour le moment, le service ne dispose d'aucune image à afficher, vous pouvez
utiliser cette syntaxe pour ajouter une image :
<div lang="en-US">
```
base64 monimage.jpg | curl --data @- http://localhost:8080/api/images/monimage
```bash
base64 monimage.jpg | curl --data @- http://localhost:8080/api/images/monimage
```
</div>
Si vous n'êtes pas particulièrement inspiré, vous pouvez ajouter ces images :
<div lang="en-US">
```
wget -O- https://you.p0m.fr/images/lynx4 | base64 | curl --data @- http://localhost:8080/api/images/lynx
wget -O- https://you.p0m.fr/images/otters | base64 | curl --data @- http://localhost:8080/api/images/otters
wget -O- https://you.p0m.fr/images/DNcrZ6u | base64 | curl --data @- http://localhost:8080/api/images/DNcrZ6u
wget -O- https://you.p0m.fr/images/raccoons | base64 | curl --data @- http://localhost:8080/api/images/raccoons
```bash
wget -O- https://you.p0m.fr/images/lynx4 | base64 | curl --data @- http://localhost:8080/api/images/lynx
wget -O- https://you.p0m.fr/images/otters | base64 | curl --data @- http://localhost:8080/api/images/otters
wget -O- https://you.p0m.fr/images/DNcrZ6u | base64 | curl --data @- http://localhost:8080/api/images/DNcrZ6u
wget -O- https://you.p0m.fr/images/raccoons | base64 | curl --data @- http://localhost:8080/api/images/raccoons
```
</div>
@ -72,8 +72,8 @@ service ne s'exécutera pas dans notre terminal !
On utilise l'option `-d` pour lancer le conteneur en tâche de fond :
<div lang="en-US">
```
docker container run -d -p 8080:8080 nemunaire/youp0m
```bash
docker container run -d -p 8080:8080 nemunaire/youp0m
```
</div>
@ -82,8 +82,8 @@ obtenir avec un `docker container ls`), nous pouvons consulter les logs du
service (en fait, les sorties standard et d'erreur) :
<div lang="en-US">
```
docker container logs 0123456789abcdef
```bash
docker container logs 0123456789abcdef
```
</div>
@ -99,8 +99,8 @@ 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 :
<div lang="en-US">
```
docker container run -d -p 8080:8081 nemunaire/youp0m
```bash
docker container run -d -p 8080:8081 nemunaire/youp0m
```
</div>
@ -117,8 +117,8 @@ Lorsque l'on souhaite stopper un conteneur lancé en tâche de fond, on utilise
son identifiant dans la commande suivante :
<div lang="en-US">
```
docker container stop 0123456789abcdef
```bash
docker container stop 0123456789abcdef
```
</div>

View file

@ -4,11 +4,11 @@ Mon premier conteneur
=====================
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">
```
docker container run hello-world
```bash
docker container run hello-world
```
</div>
@ -26,8 +26,8 @@ Nous pouvons directement utiliser le client pour rechercher une image sur le
*Store*, en utilisant la commande `search` :
<div lang="en-US">
```
docker search mariadb
```bash
docker search mariadb
```
</div>
@ -35,8 +35,8 @@ Il est possible de mettre à jour les images locales ou simplement
pré-télécharger des images depuis le Store en utilisant la commande `pull` :
<div lang="en-US">
```
docker image pull ubuntu
```bash
docker image pull ubuntu
```
</div>
@ -59,8 +59,8 @@ Par exemple, pour consulter la liste des images dont nous disposons localement
nous-même), on utilise la commande `ls` sous le type d'objets `image` :
<div lang="en-US">
```
docker image ls
```bash
docker image ls
```
</div>
@ -88,8 +88,8 @@ lancer dans le conteneur ainsi que ses éventuels arguments. Essayons d'afficher
un Hello World :
<div lang="en-US">
```
docker container run ubuntu /bin/echo "Hello World"
```bash
docker container run ubuntu /bin/echo "Hello World"
```
</div>
@ -103,8 +103,8 @@ n'utilisez pas [Alpine Linux](https://www.alpine-linux.org), vous pourriez
tenter d'utiliser son gestionnaire de paquet `apk`, via :
<div lang="en-US">
```
docker container run alpine /sbin/apk stats
```bash
docker container run alpine /sbin/apk stats
```
</div>
@ -139,16 +139,16 @@ du `run`. En fait, tout comme `git(1)` et ses sous-commandes, chaque niveau de
commande peut prendre des paramètres :
<div lang="en-US">
```
docker DOCKER_PARAMS container run RUN_OPTS image IMAGE_CMD IMAGE_ARGS ...
```bash
docker DOCKER_PARAMS container run RUN_OPTS image IMAGE_CMD IMAGE_ARGS ...
```
</div>
Par exemple :
<div lang="en-US">
```
docker -H unix:///var/run/docker.sock container run -it alpine /bin/ash -c "echo foo"
```bash
docker -H unix:///var/run/docker.sock container run -it alpine /bin/ash -c "echo foo"
```
</div>
@ -167,10 +167,10 @@ sans quoi `bash` ne se lancera pas en mode interractif[^bashnointer].
<div lang="en-US">
```
42sh$ cat cmd
echo foo
42sh$ cat cmd | docker run -i busybox
foo
42sh$ cat cmd
echo foo
42sh$ cat cmd | docker run -i busybox
foo
```
</div>
@ -186,9 +186,9 @@ conteneurs en cours d'exécution :
<div lang="en-US">
```
42sh$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4c39fc049cd1 ubuntu "/bin/bash" 6 minutes ago Up 5 minutes suspicious_galileo
42sh$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4c39fc049cd1 ubuntu "/bin/bash" 6 minutes ago Up 5 minutes suspicious_galileo
```
</div>

View file

@ -18,7 +18,7 @@ Avant de continuer, assurez-vous que votre machine a bien démarré sur un noyau
<div lang="en-US">
```
x86_64
x86_64
```
</div>
@ -26,7 +26,7 @@ Assurez-vous également d'avoir un noyau récent, avec la commande `uname -r` :
<div lang="en-US">
```
4.18.11-gentoo
4.18.11-gentoo
```
</div>
@ -82,8 +82,8 @@ un bac à sable dans lequel vous pourrez commencer à faire ce TP.
Vous devriez maintenant être capable de lancer la commande suivante :
<div lang="en-US">
```
docker version
```bash
docker version
```
</div>
@ -91,24 +91,24 @@ Une sortie similaire au bloc suivant devrait apparaître sur votre écran :
<div lang="en-US">
```
Client:
Version: 18.06.1-ce
API version: 1.38
Go version: go1.10.3
Git commit: e68fc7a
Built: Sun Sep 9 10:14:56 2018
OS/Arch: linux/amd64
Experimental: false
Client:
Version: 18.06.1-ce
API version: 1.38
Go version: go1.10.3
Git commit: e68fc7a
Built: Sun Sep 9 10:14:56 2018
OS/Arch: linux/amd64
Experimental: false
Server:
Engine:
Version: 18.06.1-ce
API version: 1.38 (minimum version 1.12)
Go version: go1.10.3
Git commit: e68fc7a
Built: Sun Sep 9 10:13:21 2018
OS/Arch: linux/amd64
Experimental: true
Server:
Engine:
Version: 18.06.1-ce
API version: 1.38 (minimum version 1.12)
Go version: go1.10.3
Git commit: e68fc7a
Built: Sun Sep 9 10:13:21 2018
OS/Arch: linux/amd64
Experimental: true
```
</div>
@ -138,8 +138,8 @@ 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 :
<div lang="en-US">
```
sudo service docker restart
```bash
sudo service docker restart
```
</div>
@ -151,8 +151,8 @@ denied.`, ajoutez votre utilisateur au groupe `docker` et **relancez votre
session** :
<div lang="en-US">
```
sudo gpasswd -a $USER docker
```bash
sudo gpasswd -a $USER docker
```
</div>

View file

@ -43,11 +43,11 @@ leur pilote. Pour consulter la liste de réseaux utilisables, lancez :
<div lang="en-US">
```
42sh$ docker network ls
NETWORK ID NAME DRIVER SCOPE
74cedd3ff385 bridge bridge local
d5d907add6e2 host host local
16b702ed01a0 none null local
42sh$ docker network ls
NETWORK ID NAME DRIVER SCOPE
74cedd3ff385 bridge bridge local
d5d907add6e2 host host local
16b702ed01a0 none null local
```
</div>
@ -78,8 +78,8 @@ La création d'un réseau se fait tout simplement au travers des sous-commandes
relatives aux objets Docker `network` :
<div lang="en-US">
```
docker network create --driver bridge my_fic
```bash
docker network create --driver bridge my_fic
```
</div>
@ -88,8 +88,8 @@ C'est ensuite ce nom de réseau que vous passerez à l'option `--network` de vos
réseau :
<div lang="en-US">
```
docker network connect NETWORK CONTAINER
```bash
docker network connect NETWORK CONTAINER
```
</div>
@ -98,7 +98,7 @@ mutuellement se découvrir grâce à un système de résolution de nom basé sur
nom de conteneur.
## Exercice
## Exercice {-}
À vous maintenant de connecter une instance de `nemunaire/fic-admin` à sa base
de données.
@ -108,8 +108,8 @@ de données avec le nom d'utilisateur et le mot de passe par défaut. Vous les
obtiendrez en lisant l'aide :
<div lang="en-US">
```
docker container run --rm -e MYSQL_HOST="tcp(mysql_cntr_name:3306)" nemunaire/fic-admin -help
```bash
docker container run --rm -e MYSQL_HOST="tcp(mysql_cntr_name:3306)" nemunaire/fic-admin -help
```
</div>
@ -126,8 +126,8 @@ utilisant :
<div lang="en-US">
```
42sh$ docker container exec -it ficadmin_cntr_name /bin/bash
(incntnr)# ping mysql_cntr_name
42sh$ docker container exec -it ficadmin_cntr_name /bin/bash
(incntnr)# ping mysql_cntr_name
```
</div>

View file

@ -38,13 +38,13 @@ a pu voir durant ce premier cours.
### Exemple d'exécution
<div lang="en-US">
```
42sh$ ./mycloud-run.sh
http://localhost:12345/
42sh$ #docker kill db
42sh$ ./mycloud-run.sh # le script relancera une base de données,
# sans avoir perdu les données
http://localhost:12345/
```bash
42sh$ ./mycloud-run.sh
http://localhost:12345/
42sh$ #docker kill db
42sh$ ./mycloud-run.sh # le script relancera une base de données,
# sans avoir perdu les données
http://localhost:12345/
```
</div>
@ -73,8 +73,8 @@ Voici une arborescence type:
<div lang="en-US">
```
login_x-TP1/
login_x-TP1/mycloud-run.sh
login_x-TP1/
login_x-TP1/mycloud-run.sh
```
</div>
@ -110,12 +110,12 @@ Si vous recevez un rapport avec l'erreur suivante :
<div lang="en-US">
```
[FAIL] Bad signature. Here is the gnupg output:
[FAIL] Bad signature. Here is the gnupg output:
gpg: Signature made Tue Jan 01 16:42:23 2014 CET
gpg: using RSA key 842807A84573CC96
gpg: requesting key E2CCD99DD37BD32E from hkp server pool.sks-keyservers.net
gpg: Can't check signature: No public key
gpg: Signature made Tue Jan 01 16:42:23 2014 CET
gpg: using RSA key 842807A84573CC96
gpg: requesting key E2CCD99DD37BD32E from hkp server pool.sks-keyservers.net
gpg: Can't check signature: No public key
```
</div>
@ -132,7 +132,7 @@ Si vous recevez un rapport avec l'erreur suivante :
<div lang="en-US">
```
[FAIL] The username of your key is not explicit, I can't find you.
[FAIL] The username of your key is not explicit, I can't find you.
```
</div>
@ -147,7 +147,7 @@ Si vous recevez un rapport concluant ainsi :
<div lang="en-US">
```
After analyzing your e-mail, I've decided to SKIP it.
After analyzing your e-mail, I've decided to SKIP it.
```
</div>

View file

@ -1,22 +1,23 @@
---
title: Virtualisation légère -- TP n^o^ 1
subtitle: Les bases de Docker
author: Pierre-Olivier *Nemunaire* Mercier
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA
date: Jeudi 4 octobre 2018
abstract: |
Durant ce premier TP, nous allons apprendre à utiliser Docker !
\vspace{1em}
Le TP se termine par un petit projet à rendre à <virli@nemunai.re>
au plus tard le jeudi 18 octobre 2018 à 8 h 42, des questions de
cours sont également à compléter avant cette date sur
Epitaf. Consultez la dernière partie de ce TP pour les modalités.
En tant que personnes sensibilisées à la sécurité des échanges
électroniques, vous devrez m'envoyer vos rendus signés avec votre
clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96)
faire signer votre clef et n'hésitez pas à [faire signer la
votre](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
...
Durant ce premier TP, nous allons apprendre à utiliser Docker !
Le TP se termine par un petit projet à rendre à <virli@nemunai.re> au plus tard
le jeudi 18 octobre 2018 à 8 h 42, des questions de cours sont également à
compléter avant cette date sur Epitaf. Consultez la dernière partie de ce TP
pour les modalités.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
[faire signer la votre](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
\tableofcontents

View file

@ -28,8 +28,8 @@ le protocole HTTP, mais sans se casser la tête à installer et configurer un
serveur web :
<div lang="en-US">
```
docker container run --rm -p 80:80 -v ~/Downloads:/usr/share/nginx/html:ro -d nginx
```bash
docker container run --rm -p 80:80 -v ~/Downloads:/usr/share/nginx/html:ro -d nginx
```
</div>
@ -48,26 +48,26 @@ Comme il s'agit d'un objet, la première chose à faire va être de créer notre
volume :
<div lang="en-US">
```
docker volume create prod_youp0m
docker volume create prod_foodp0m
```bash
docker volume create prod_youp0m
docker volume create prod_foodp0m
```
</div>
Ensuite, nous pouvons démarrer un conteneur utilisant, par exemple :
<div lang="en-US">
```
docker container run --mount source=prod_youp0m,target=/srv/images nemunaire/youp0m
```bash
docker container run --mount source=prod_youp0m,target=/srv/images nemunaire/youp0m
```
</div>
On pourra également faire de même avec un conteneur MySQL :
<div lang="en-US">
```
docker container run --name mydb --mount source=prod_db,target=/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=my-secret-pw mysql
```bash
docker container run --name mydb --mount source=prod_db,target=/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=my-secret-pw mysql
```
</div>
@ -78,8 +78,8 @@ Si plus tard, vous souhaitez créer un conteneur chargé de faire des
sauvegardes, vous pourriez le lancer comme ceci :
<div lang="en-US">
```
docker container run -it --volume-from mydb busybox /bin/bash
```bash
docker container run -it --volume-from mydb busybox /bin/bash
```
</div>
@ -90,11 +90,11 @@ Lorsque vous n'avez pas besoin de stocker les données et que vous ne désirez
pas qu'elles persistent (des données sensibles par exemple) ou si cela peut
améliorer les performances de votre conteneur, il est possible de créer des
points de montages utilisant le système de fichiers `tmpfs` et donc résidant
exclusivement en RAM :
exclusivement en RAM\ :
<div lang="en-US">
```
docker container run --mount type=tmpfs,target=/srv/images nemunaire/youp0m
```bash
docker container run --mount type=tmpfs,target=/srv/images nemunaire/youp0m
```
</div>

View file

@ -1,19 +1,6 @@
include ../pandoc-opts.mk
SOURCES = tutorial.md clair.md oci.md registry.md runc.md linuxkit.md rendu.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=fr-FR \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
-M colorlinks=true \
-M linkcolor="black" \
-M urlcolor="[rgb]{0.2,0.6,0.4}" \
--include-in-header=../header.tex
all: tutorial.pdf

View file

@ -1,7 +1,7 @@
\newpage
Une vision plus Clair de la sécurité ?
======================================
Une vision plus Clair de la sécurité
====================================
Nous avons vu, au travers de tous les précédents TP, que Docker nous apportait
un certain degré de sécurité d'emblée au lancement du conteneur. Cela peut sans
@ -86,9 +86,9 @@ Une fois lancé, la base nécessite d'être initialisée. L'opération peut pren
plusieurs minutes. Vous pouvez suivre l'avancement de l'ajout :
<div lang="en-US">
```shell
curl http://localhost:6060/v1/namespaces
curl http://localhost:6060/v1/namespaces/debian:9/vulnerabilities?limit=10
```bash
curl http://localhost:6060/v1/namespaces
curl http://localhost:6060/v1/namespaces/debian:9/vulnerabilities?limit=10
```
</div>
@ -100,8 +100,8 @@ conteneur, nous allons utiliser le programme
[`paclair`](https://github.com/yebinama/paclair) :
<div lang="en-US">
```shell
pip3 install paclair
```bash
pip3 install paclair
```
</div>
@ -109,11 +109,11 @@ Il nécessite un fichier de configuration pour être utilisé, essayez :
<div lang="en-US">
```yml
General:
clair_url: 'http://localhost:6060'
Plugins:
Docker:
class: paclair.plugins.docker_plugin.DockerPlugin
General:
clair_url: 'http://localhost:6060'
Plugins:
Docker:
class: paclair.plugins.docker_plugin.DockerPlugin
```
</div>
@ -121,33 +121,33 @@ Pour obtenir un rapport d'analyse, on commence par envoyer les couches de
l'image à `Clair` :
<div lang="en-US">
```shell
paclair --conf conf.yml Docker nemunaire/fic-admin push
```bash
paclair --conf conf.yml Docker nemunaire/fic-admin push
```
</div>
Puis on lui demande la génération d'un rapport `html` :
<div lang="en-US">
```shell
paclair --conf conf.yml Docker nemunaire/fic-admin analyse --output-format html --output-report file
```bash
paclair --conf conf.yml Docker nemunaire/fic-admin analyse --output-format html --output-report file
```
</div>
Si l'on souhaite uniquement avoir des statistiques dans la console :
<div lang="en-US">
```shell
42sh$ paclair --conf conf.yml Docker node:latest analyse --output-format stats
Unknown: 2
Negligible: 1
Medium: 5
High: 4
```bash
42sh$ paclair --conf conf.yml Docker node:latest analyse --output-format stats
Unknown: 2
Negligible: 1
Medium: 5
High: 4
```
</div>
## Exercice {.unnumbered}
## Exercice {-}
Déterminez le nombre de vulnérabilités dans les principales images officielles
du [Docker Hub](https://hub.docker.com/explore), notamment `nginx`, `golang`,

View file

@ -67,25 +67,25 @@ L'image la plus simple que l'on puisse réaliser pourrait être :
<div lang="en-US">
```yaml
kernel:
image: linuxkit/kernel:4.14.80
cmdline: "console=tty0 console=ttyS0"
init:
- linuxkit/init:c563953a2277eb73a89d89f70e4b6dcdcfebc2d1
- linuxkit/runc:83d0edb4552b1a5df1f0976f05f442829eac38fe
- linuxkit/containerd:326b096cd5fbab0f864e52721d036cade67599d6
onboot:
- name: dhcpcd
image: linuxkit/dhcpcd:v0.6
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
services:
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
env:
- INSECURE=true
trust:
org:
- linuxkit
kernel:
image: linuxkit/kernel:4.14.80
cmdline: "console=tty0 console=ttyS0"
init:
- linuxkit/init:c563953a2277eb73a89d89f70e4b6dcdcfebc2d1
- linuxkit/runc:83d0edb4552b1a5df1f0976f05f442829eac38fe
- linuxkit/containerd:326b096cd5fbab0f864e52721d036cade67599d6
onboot:
- name: dhcpcd
image: linuxkit/dhcpcd:v0.6
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
services:
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
env:
- INSECURE=true
trust:
org:
- linuxkit
```
</div>
@ -102,7 +102,7 @@ la partie `init`, elle sera alors lancé comme un équivalent de
<https://github.com/linuxkit/linuxkit/blob/master/pkg/getty/README.md#linuxkit-debug>
## *namespaces*
## `namespaces`
Chaque nouveau conteneur est donc lancé dans un espace distinct où il ne pourra
pas interagir avec les autres, ou déborder s'il s'avérait qu'il expose une
@ -117,9 +117,9 @@ Il reste possible de se dissocier également de ces namespaces, en précisant :
<div lang="en-US">
```yaml
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
net: new
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
net: new
```
</div>
@ -127,14 +127,14 @@ Ou inversement, pour persister dans le namespace initial :
<div lang="en-US">
```yaml
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
pid: host
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
pid: host
```
</div>
### Partage de *namespace*
### Partage de `namespace`
Dans le cas où l'on souhaite que deux conteneurs partagent le même *namespace*,
il faut passer le chemin vers la structure du noyau correspondante.
@ -144,11 +144,11 @@ On commence donc d'abord par créer le nouveau *namespace*, en prenant soin de
<div lang="en-US">
```yaml
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
net: new
runtime:
bindNS: /run/netns/mynewnetns
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
net: new
runtime:
bindNS: /run/netns/mynewnetns
```
</div>
@ -158,9 +158,9 @@ réutiliser plus tard ce chemin, en remplacement du mot clef `new` :
<div lang="en-US">
```yaml
- name: xxxx
image: linuxkit/xxxx:v0.6
net: /run/netns/mynewnetns
- name: xxxx
image: linuxkit/xxxx:v0.6
net: /run/netns/mynewnetns
```
</div>
@ -175,8 +175,8 @@ plates-formes pour aller y lancer des instances de cette image !
Pour construire l'image faite précédemment :
<div lang="en-US">
```shell
linuxkit build hello.yml
```bash
linuxkit build hello.yml
```
</div>
@ -185,8 +185,8 @@ partie `kernel`) ainsi qu'une image. Exactement ce qu'attend QEMU ! Pour
tester, n'attendons pas davantage pour lancer :
<div lang="en-US">
```shell
linuxkit run qemu -gui hello
```bash
linuxkit run qemu -gui hello
```
</div>
@ -199,8 +199,8 @@ serveur SSH aux `services` :
<div lang="en-US">
```yaml
- name: sshd
image: linuxkit/sshd:c4bc89cf0d66733c923ab9cb46198b599eb99320
- name: sshd
image: linuxkit/sshd:c4bc89cf0d66733c923ab9cb46198b599eb99320
```
</div>
@ -209,9 +209,9 @@ SSH pour se connecter. Voilà un bon début d'utilisation de la section `files`
<div lang="en-US">
```yaml
- path: root/.ssh/authorized_keys
source: ~/.ssh/id_rsa.pub
mode: "0600"
- path: root/.ssh/authorized_keys
source: ~/.ssh/id_rsa.pub
mode: "0600"
```
</div>
@ -230,21 +230,21 @@ une interface `virtual ethernet` :
<div lang="en-US">
```yaml
- name: db
image: mariadb:latest
net: new
runtime:
bindNS:
net: /run/netns/db
interfaces:
- name: vethin-db
add: veth
peer: veth-db
- name: db
image: mariadb:latest
net: new
runtime:
bindNS:
net: /run/netns/db
interfaces:
- name: vethin-db
add: veth
peer: veth-db
```
</div>
## Exercice
## Exercice {-}
Réalisez une recette `vault.yml` démarrant une instance du gestionnaire de
secrets [Hashicorp Vault](https://www.vaultproject.io/), utilisant une [base de

View file

@ -75,7 +75,7 @@ Dernière née de l'organisme, cette spécification fédère la notion de
aussi en envoyer.
## Pour aller plus loin
## Pour aller plus loin {-}
Si maintenant `docker` fait appel à un programme externe pour lancer
effectivement nos conteneurs, c'est que l'on peut changer cette implémentation

View file

@ -3,6 +3,8 @@ Registres
**Outils nécessaires :** `curl`, `gunzip`, `jq`, `tar`.
* * * * *
Dans cette partie, nous allons appréhender le fonctionnement d'un registre OCI,
et préparer le *rootfs* d'une image de base (Debian, Ubuntu, hello, ...) : en
nous préoccupant simplement de la couche la plus basse (qui ne contient pas de
@ -24,23 +26,23 @@ intéresse aujourd'hui !
Il n'en reste pas moins que le jeton est forgé pour un service donné (dans
notre cas `registry.docker.io`) et avec un objectif bien cerné (pour nous, on
souhaite récupérer le contenu du dépôt[^quiddepot] `hello-world` :
`repository:hello-world:pull`). Ce qui nous donne :
<span lang="en-US">`repository:hello-world:pull`</span>). Ce qui nous donne :
[^quiddepot]: Dans un registre, les fichiers qui composent l'image forment un
dépôt (*repository*).
<div lang="en-US">
```shell
42sh$ curl "https://auth.docker.io/token"\
> "?service=registry.docker.io&scope=repository:library/hello-world:pull" | jq .
```bash
42sh$ curl "https://auth.docker.io/token?service=registry.docker.io&"\
> "scope=repository:library/hello-world:pull" | jq .
```
```json
{
"token": "lUWXBCZzg2TGNUdmMy...daVZxGTj0eh",
"access_token": "eyJhbGciOiJSUzI1NiIsI...N5q469M3ZkL_HA",
"expires_in": 300,
"issued_at": "2012-12-12T12:12:12.123456789Z"
}
{
"token": "lUWXBCZzg2TGNUdmMy...daVZxGTj0eh",
"access_token": "eyJhbGciOiJSUzI1NiIsI...N5q469M3ZkL_HA",
"expires_in": 300,
"issued_at": "2012-12-12T12:12:12.123456789Z"
}
```
</div>
@ -50,8 +52,8 @@ registre.
Avec `jq`, on peut l'extraire grâce à :
<div lang="en-US">
```shell
| jq -r .token
```bash
| jq -r .token
```
</div>
@ -62,11 +64,11 @@ Une fois en possession de notre jeton, nous pouvons maintenant demander l'index
d'images à notre registre :
<div lang="en-US">
```shell
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.docker.distribution.manifest.list.v2+json" \
"https://registry-1.docker.io/v2/library/hello-world/manifests/latest" | jq .
```bash
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.docker.distribution.manifest.list.v2+json" \
"https://registry-1.docker.io/v2/library/hello-world/manifests/latest" | jq .
```
</div>
@ -81,11 +83,11 @@ Demandons maintenant le manifest correspondant à notre matériel et à notre
système d'exploitation :
<div lang="en-US">
```shell
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: ${MEDIATYPE}" \
"https://registry-1.docker.io/v2/library/hello-world/manifests/${MANIFEST_DIGEST}" | jq .
```bash
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: ${MEDIATYPE}" \
"https://registry-1.docker.io/v2/library/hello-world/manifests/${MANIFEST_DIGEST}" | jq .
```
</div>
@ -101,10 +103,10 @@ répertoire `blobs`, il ne s'agit en effet plus de manifest. Si les manifests so
Pour récupérer la configuration de l'image :
<div lang="en-US">
```shell
curl -s --location \
-H "Authorization: Bearer ${TOKEN}" \
"https://registry-1.docker.io/v2/library/hello-world/blobs/${CONFIG_DIGEST}" | jq .
```bash
curl -s --location \
-H "Authorization: Bearer ${TOKEN}" \
"https://registry-1.docker.io/v2/library/hello-world/blobs/${CONFIG_DIGEST}" | jq .
```
</div>
@ -112,9 +114,9 @@ Pour récupérer la configuration de l'image :
Enfin, armé du `digest` de notre couche, il ne nous reste plus qu'à la demander gentiment :
<div lang="en-US">
```shell
wget --header "Authorization: Bearer ${TOKEN}" \
"https://registry-1.docker.io/v2/library/hello-world/blobs/${LAYER_DIGEST}"
```bash
wget --header "Authorization: Bearer ${TOKEN}" \
"https://registry-1.docker.io/v2/library/hello-world/blobs/${LAYER_DIGEST}"
```
</div>
@ -126,40 +128,40 @@ Le type indiqué par le manifest pour cette couche était
tarball compressée au format gzip :
<div lang="en-US">
```shell
mkdir rootfs
tar xzf ${DL_LAYER} -C rootfs
```bash
mkdir rootfs
tar xzf ${DL_LAYER} -C rootfs
```
</div>
Et voilà, nous avons extrait notre première image, nous devrions pouvoir :
<div lang="en-US">
```shell
42sh# chroot rootfs /hello
Hello from Docker!
[...]
```bash
42sh# chroot rootfs /hello
Hello from Docker!
[...]
```
</div>
## Exercice {.unnumbered}
## Exercice {-}
Réalisez un script pour automatiser l'ensemble de ces étapes :
<div lang="en-US">
```shell
42sh$ cd $(mktemp)
```bash
42sh$ cd $(mktemp)
42sh$ ~/workspace/registry_play.sh library/hello
42sh$ ~/workspace/registry_play.sh library/hello
42sh$ find
.
./rootfs
./rootfs/hello
42sh$ find
.
./rootfs
./rootfs/hello
42sh# chroot rootfs /hello
Hello from Docker!
[...]
42sh# chroot rootfs /hello
Hello from Docker!
[...]
```
</div>

View file

@ -30,13 +30,13 @@ cela dépendra de votre avancée dans le projet) :
<div lang="en-US">
```
login_x-TP5/
login_x-TP5/docker-compose.yml
login_x-TP5/clair_config/config.yaml
login_x-TP5/nginx:mainline.html
login_x-TP5/registry_play.sh
login_x-TP5/config.json
login_x-TP5/vault.yml
login_x-TP5/pkg/...
login_x-TP5/
login_x-TP5/docker-compose.yml
login_x-TP5/clair_config/config.yaml
login_x-TP5/nginx:mainline.html
login_x-TP5/registry_play.sh
login_x-TP5/config.json
login_x-TP5/vault.yml
login_x-TP5/pkg/...
```
</div>

View file

@ -32,7 +32,13 @@ vous pouvez télécharger la dernière version :
d'alpine : `library/alpine` dans le registre Docker.
Si vous n'avez pas eu le temps de terminer l'exercice précédent, vous pouvez
utiliser `docker image save alpine | tar xv -C rootfs`.
utiliser :
<div lang="en-US">
```bash
docker image save alpine | tar xv -C rootfs
```
</div>
## Modèle de configuration
@ -42,8 +48,8 @@ fastidieux et répétitif, nous allons donc gagner du temps et utiliser la
commande suivante, qui nous créera un modèle que nous adapterons un peu :
<div lang="en-US">
```shell
runc spec
```bash
runc spec
```
</div>
@ -56,12 +62,12 @@ Pour savoir à quoi correspondent tous ces éléments, vous pouvez consulter :
Voici comment nous pouvons tester le fonctionnement de notre *bundle* :
<div lang="en-US">
```shell
42sh$ ls
rootfs/ config.json
```
42sh$ ls
rootfs/ config.json
42sh# runc run --bundle . virli1
/ # _
42sh# runc run --bundle . virli1
/ # _
```
</div>
@ -70,34 +76,34 @@ retrouver tout l'écosystème de `docker` ; ici il n'y a pas de gestion des
journaux, etc. :
<div lang="en-US">
```shell
42sh# runc list
ID PID STATUS BUNDLE CREATED OWNER
virli1 12345 running /tmp/work/runctest 2012-12-12T12:12:12.123456789Z root
```bash
42sh# runc list
ID PID STATUS BUNDLE CREATED OWNER
virli1 12345 running /tmp/work/runctest 2012-12-12T12:12:12.123456789Z root
42sh# runc state virli1
...
42sh# runc state virli1
...
```
</div>
## Attacher notre *home*
## Attacher notre `home`
Dans le modèle de `config.json`, il y a déjà de nombreux systèmes de fichiers
qui sont montés. Nous pouvons les filtrer avec :
<div lang="en-US">
```shell
42sh$ jq .mounts config.json
```bash
42sh$ jq .mounts config.json
```
```json
[
{
"destination": "/proc",
"type": "proc",
"source": "proc"
},
[...]
[
{
"destination": "/proc",
"type": "proc",
"source": "proc"
},
[...]
```
</div>
@ -106,25 +112,25 @@ ajouter un élément à cette liste, demandant de *bind* :
<div lang="en-US">
```json
{
"destination": "/home",
"type": "none",
"source": "/home",
"options": [
{
"destination": "/home",
"type": "none",
"source": "/home",
"options": [
"bind",
"ro"
]
}
}
```
</div>
## Exercice
## Exercice {-}
Serez-vous capable de continuer l'édition de votre `config.json` afin d'obtenir
les mêmes restrictions que votre projet de moulette ?
* CGroups : 1GB RAM, 100 PID, ...
* CGroups : 1\ GB RAM, 100\ PIDs, ...
* strict minimum de capabilities ;
* filtres `seccomp` ;
* carte réseau `veth` ;

View file

@ -1,22 +1,23 @@
---
title: Virtualisation légère -- TP n^o^ 5
subtitle: Docker Internals
author: Pierre-Olivier *Nemunaire* Mercier
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA
date: Mercredi 14 novembre 2018
abstract: |
Dans ce cinquième du TP, nous allons entrer dans les sous-bassements de
Docker !
\vspace{1em}
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le dimanche 25 novembre 2018 à 23
h 42. Consultez la dernière section de chaque partie pour plus d'information
sur les éléments à rendre.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96)
faire signer votre clef et n'hésitez pas à [faire signer votre
clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
...
Dans ce cinquième du TP, nous allons entrer dans les sous-bassements de Docker !
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le dimanche 25 novembre 2018 à 23 h 42. Consultez la
dernière section de chaque partie pour plus d'information sur les éléments à
rendre.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
[faire signer votre clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
\tableofcontents

View file

@ -1,19 +1,6 @@
include ../pandoc-opts.mk
SOURCES = tutorial.md setup.md machine.md swarm.md stack.md rendu.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=fr-FR \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
-M colorlinks=true \
-M linkcolor="black" \
-M urlcolor="[rgb]{0.2,0.6,0.4}" \
--include-in-header=../header.tex
all: tutorial.pdf

View file

@ -55,8 +55,8 @@ 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) :
<div lang="en-US">
```shell
docker-machine create --driver virtualbox echinoidea
```bash
docker-machine create --driver virtualbox echinoidea
```
</div>
@ -81,14 +81,14 @@ avec `docker-machine` cela prend tout son sens, car vous pouvez très facilement
changer de daamon/machine avec une simple commande :
<div lang="en-US">
```shell
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS
$ eval $(docker-machine env echinoidea)
$ 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
```
42sh$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS
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>
@ -141,20 +141,20 @@ Commençons par voir sur quel port le daemon `dockerd` de notre machine
virtuelle écoute :
<div lang="en-US">
```shell
(virt1) 42sh$ netstat -tpln | grep dockerd
Proto Recv-Q Send-Q Local Address Foreign Address PID/Program name
tcp 0 0 :::2376 :::* 980/dockerd
```bash
(virt1) 42sh$ netstat -tpln | grep dockerd
Proto Recv-Q Send-Q Local Address Foreign Address PID/Program name
tcp 0 0 :::2376 :::* 980/dockerd
```
</div>
Essayons de renseigner simplement cette configuration à notre client Docker :
<div lang="en-US">
```shell
(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".
* Are you trying to connect to a TLS-enabled daemon without TLS?
```bash
(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".
* Are you trying to connect to a TLS-enabled daemon without TLS?
```
</div>
@ -173,20 +173,20 @@ Tout le nécessaire est déjà configuré au sein de `boot2docker`, pour nos tes
nous n'avons qu'à recopier la clef et les certificats en place.
<div lang="en-US">
```shell
(main) 42sh$ mkdir remote/virt1
(main) 42sh$ scp "docker@$VM1_IP:.docker/*" remote/virt1
ca.pem
cert.pem
key.pem
```bash
(main) 42sh$ mkdir remote/virt1
(main) 42sh$ scp "docker@$VM1_IP:.docker/*" remote/virt1
ca.pem
cert.pem
key.pem
```
</div>
Tentons maintenant de nous connecter au daemon distant en utilisant ces éléments :
<div lang="en-US">
```shell
42sh$ DOCKER_CERT_PATH=remote/virt1/ docker -H tcp://$VM1_IP:2376/ --tlsverify info
```bash
42sh$ DOCKER_CERT_PATH=remote/virt1/ docker -H tcp://$VM1_IP:2376/ --tlsverify info
```
</div>

View file

@ -38,8 +38,8 @@ cela dépendra de votre avancée dans le projet) :
<div lang="en-US">
```
login_x-TP2/
login_x-TP2/mymonitoring-stack.yml
login_x-TP2/
login_x-TP2/mymonitoring-stack.yml
```
</div>

View file

@ -27,10 +27,10 @@ pour bon nombres d'environnements. Nous pouvons l'installer en suivant la
procédure suivante :
<div lang="en-US">
```shell
curl -L https://github.com/docker/machine/releases/download/v0.15.0/docker-machine-Linux-x86_64 \
> /usr/bin/docker-machine
chmod +x /usr/bin/docker-machine
```bash
curl -L https://github.com/docker/machine/releases/download/v0.15.0/docker-machine-Linux-x86_64 \
> /usr/bin/docker-machine
chmod +x /usr/bin/docker-machine
```
</div>
@ -59,8 +59,8 @@ Comme avec Docker, nous pouvons vérifier le bon fonctionnement de
<div lang="en-US">
```
42sh$ docker-machine version
docker-machine version 0.12.2, build 9371605
42sh$ docker-machine version
docker-machine version 0.12.2, build 9371605
```
</div>

View file

@ -27,8 +27,8 @@ 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 :
<div lang="en-US">
```shell
docker container run --name mywebs -d nginx
```bash
docker container run --name mywebs -d nginx
```
</div>
@ -36,8 +36,8 @@ La même commande, mais déployée à partir d'un nœud manager, vers un nœud
*workers*, est :
<div lang="en-US">
```shell
docker service create --name myWebS nginx
```bash
docker service create --name myWebS nginx
```
</div>
@ -46,10 +46,10 @@ Allons-y, essayons !
On peut consulter l'état du service avec, comme d'habitude `ls` :
<div lang="en-US">
```shell
42sh$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
iyue3rgd0ohs myWebS replicated 1/1 nginx:latest
```
42sh$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
iyue3rgd0ohs myWebS replicated 1/1 nginx:latest
```
</div>
@ -62,8 +62,8 @@ Rien de très excitant pour le moment, car nous ne pouvons pas vraiment accéder
d'ajouter une redirection de port :
<div lang="en-US">
```shell
docker service update --publish-add 80 myWebS
```bash
docker service update --publish-add 80 myWebS
```
</div>
@ -109,16 +109,16 @@ Ce qui se fait souvent avec beaucoup de douleur hors de Docker, se résume ici
:
<div lang="en-US">
```shell
docker service update --replicas 3 myWebS
```bash
docker service update --replicas 3 myWebS
```
</div>
Roulement de tambours .......
<div lang="en-US">
```shell
docker service ps myWebS
```bash
docker service ps myWebS
```
</div>
@ -139,8 +139,8 @@ Notre système de monitoring est une *stack* lui aussi, d'ailleurs, nous pouvons
la lancer grâce à notre `docker-compose.yml` :
<div lang="en-US">
```shell
docker stack deploy --compose-file docker-compose.yml tic
```bash
docker stack deploy --compose-file docker-compose.yml tic
```
</div>
@ -151,23 +151,23 @@ paramètres qui ne serviront qu'au déploiement de notre tâche.
<div lang="en-US">
```yaml
version: '3'
services:
redis:
image: redis:alpine
version: '3'
services:
redis:
image: redis:alpine
deploy:
replicas: 6
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
placement:
constraints:
- node.role == manager
resources:
memory: 50M
deploy:
replicas: 6
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
placement:
constraints:
- node.role == manager
resources:
memory: 50M
```
</div>

View file

@ -77,8 +77,8 @@ La première chose à faire, est d'initialiser un cluster swarm. Pour se faire,
ce n'est pas plus compliqué que de faire :
<div lang="en-US">
```shell
docker swarm init
```bash
docker swarm init
```
</div>
@ -98,8 +98,8 @@ lorsque vous initialisez le cluster. Si vous avez raté la sortie de la
commande, vous pouvez retrouver le jeton avec :
<div lang="en-US">
```shell
docker swarm join-token worker
```bash
docker swarm join-token worker
```
</div>
@ -119,21 +119,21 @@ utilisant `docker-machine`.
des redirections de ports, mais le résultat n'est pas garanti !
<div lang="en-US">
```shell
eval $(docker-machine env echinoidea)
docker swarm join --token SWMTKN-1-...-... 10.10.10.42:2377
```bash
eval $(docker-machine env echinoidea)
docker swarm join --token SWMTKN-1-...-... 10.10.10.42:2377
```
</div>
Une fois rejoint, vous devriez voir apparaître un nouveau nœud *worker* dans :
<div lang="en-US">
```shell
42sh$ eval $(docker-machine env -u)
42sh$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
y9skzvuf989hjrkciu8mnsy echinoidea Ready Active
ovgh6r32kgcbswb2we48br1 * wales Ready Active Leader
```
42sh$ eval $(docker-machine env -u)
42sh$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
y9skzvuf989hjrkciu8mnsy echinoidea Ready Active
ovgh6r32kgcbswb2we48br1 * wales Ready Active Leader
```
</div>

View file

@ -1,22 +1,24 @@
---
title: Virtualisation légère -- TP n^o^ 2.3
subtitle: L'orchestration avec Docker
author: Pierre-Olivier *Nemunaire* Mercier
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA
date: Jeudi 18 octobre 2018
abstract: |
Dans la troisième partie de ce TP, nous allons orchestrer nos
conteneurs !
\vspace{1em}
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le mercredi 24 octobre 2018 à 0
h 42. Consultez la dernière section de chaque partie pour plus
d'information sur les éléments à rendre.
En tant que personnes sensibilisées à la sécurité des échanges
électroniques, vous devrez m'envoyer vos rendus signés avec votre
clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96)
faire signer votre clef et n'hésitez pas à [faire signer votre
clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
...
Dans la troisième partie de ce TP, nous allons orchestrer nos conteneurs !
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le mercredi 24 octobre 2018 à 0 h 42. Consultez la
dernière section de chaque partie pour plus d'information sur les éléments à
rendre.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
[faire signer votre clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
\tableofcontents

View file

@ -1,19 +1,6 @@
include ../pandoc-opts.mk
SOURCES = tutorial.md interactive.md dockerfile.md goodpractices.md entrypoint.md rendu.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=fr-FR \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
-M colorlinks=true \
-M linkcolor="black" \
-M urlcolor="[rgb]{0.2,0.6,0.4}" \
--include-in-header=../header.tex
all: tutorial.pdf

View file

@ -9,11 +9,11 @@ construction de nouvelles images. Nous pouvons arriver au même résultat que ce
que l'on a réussi à faire précédemment en utilisant le `Dockerfile` suivant :
<div lang="en-US">
```
FROM ubuntu:latest
```dockerfile
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y nano
RUN apt-get update
RUN apt-get install -y nano
```
</div>
@ -21,17 +21,17 @@ La syntaxe d'un `Dockerfile` est simple : le premier mot de chaque ligne est
l'intitulé d'une instruction (que l'on écrit généralement en majuscule), elle
est suivie de ses arguments.
Dans notre exemple, nous utilisons `FROM` qui indique une image de départ à
utiliser ; `RUN` est une commande qui sera exécutée dans le conteneur, dans le
but de le construire.
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
le conteneur, dans le but de le construire.
Pour lancer la construction de la nouvelle image, créons un nouveau dossier ne
contenant que votre fichier `Dockerfile`, plaçons-nous ensuite dedans, puis
lançons la commande `build` :
<div lang="en-US">
```
docker image build --tag=my_editor .
```bash
docker image build --tag=my_editor .
```
</div>
@ -39,8 +39,8 @@ Une fois la construction de l'image terminée, nous pouvons la lancer et
constater l'existence de notre éditeur favori :
<div lang="en-US">
```
docker container run -it my_editor /bin/bash
```bash
docker container run -it my_editor /bin/bash
```
</div>
@ -53,23 +53,23 @@ correspondra à une nouvelle couche de notre image.
Cela signifie que l'exemple suivant **ne fonctionne pas** :
<div lang="en-US">
```
COPY db.sql /db.sql
RUN service mysqld start
RUN mysql -u root -p toor virli < /db.sql
```dockerfile
COPY db.sql /db.sql
RUN service mysqld start
RUN mysql -u root -p toor virli < /db.sql
```
</div>
Cet exemple ne fonctionne pas car le serveur MySQL est bien lancé dans le
premier `RUN`, mais il se trouve brûtalement arrêté dès lors que la commande
`service` se termine. En fait, à chaque instruction, Docker réalise
premier `RUN`{.dockerfile}, mais il se trouve brûtalement arrêté dès lors que
la commande `service` se termine. En fait, à chaque instruction, Docker réalise
automatiquement un `run` suivi d'un `commit`. Et vous pouvez constater par
vous-même que, en créant l'image `tinysql` à partir d'un simple `apt install
mysql` :
<div lang="en-US">
```
docker container run tinysql service mysqld start
```bash
docker container run tinysql service mysqld start
```
</div>
@ -79,16 +79,16 @@ processus.
Pour avoir le résultat escompté, il faut exécuter les commandes ensemble :
<div lang="en-US">
```
COPY db.sql /db.sql
RUN service mysqld start && mysql -u root -p toor virli < /db.sql
```dockerfile
COPY db.sql /db.sql
RUN service mysqld start && mysql -u root -p toor virli < /db.sql
```
</div>
Après le `RUN`, MySQL sera de nouveau tué.
Après le `RUN`{.dockerfile}, MySQL sera de nouveau tué.
En aucun cas, une commande exécutée par un `RUN` se retrouvera en cours
d'exécution lorsque l'on invoquera un conteneur par `docker container
En aucun cas, une commande exécutée par un `RUN`{.dockerfile} se retrouvera en
cours d'exécution lorsque l'on invoquera un conteneur par `docker container
run`. Seul la commande fournie par l'utilisateur ou la commande par défaut de
l'image sera exécutée au lancement d'un conteneur.
@ -98,17 +98,17 @@ l'image sera exécutée au lancement d'un conteneur.
Construisons maintenant un conteneur avec un service web :
<div lang="en-US">
```
FROM my_editor
```dockerfile
FROM my_editor
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get update
RUN apt-get install -y nginx
EXPOSE 80
EXPOSE 80
```
</div>
L'instruction `EXPOSE` sera traitée plus tard par le client Docker (équivalent
L'instruction `EXPOSE`{.dockerfile} sera traitée plus tard par le client Docker (équivalent
à l'argument `--expose`). Il s'agit d'une métadonnée qui sera attachée à
l'image (et à toutes ses images filles).
@ -119,9 +119,9 @@ conteneur :
<div lang="en-US">
```
42sh$ docker image build --tag=my_webserver .
42sh$ docker container run -it -P my_webserver /bin/bash
(cntnr)# service nginx start
42sh$ docker image build --tag=my_webserver .
42sh$ docker container run -it -P my_webserver /bin/bash
(cntnr)# service nginx start
```
</div>
@ -130,7 +130,7 @@ Dans un autre terminal, lancer un `docker container ls` et consulter la colonne
Rendez-vous ensuite dans votre navigateur sur <http://localhost:49153/>.
*À vous de jouer :* utilisez l'instruction `COPY` pour afficher votre propre
**À vous de jouer :** utilisez l'instruction `COPY`{.dockerfile} pour afficher votre propre
`index.html` remplaçant celui installé de base par `nginx`. Si vous manquez
d'inspiration, utilisez [cette page de compte à
rebours](https://virli.nemunai.re/countdown.html).
@ -169,22 +169,22 @@ images), en haut du `Dockerfile`.
## Métadonnées pures
L'instruction LABEL permet d'ajouter une métadonnée à une image, sous forme de
clef/valeur.
L'instruction `LABEL`{.dockerfile} permet d'ajouter une métadonnée à une image,
sous forme de clef/valeur.
Une métadonnée
[courante](https://github.com/nginxinc/docker-nginx/blob/master/mainline/stretch/Dockerfile#L3)
est d'indiquer le nom du mainteneur de l'image :
<div lang="en-US">
```
LABEL maintainer="Pierre-Olivier Mercier <nemunaire@nemunai.re>"
```dockerfile
LABEL maintainer="Pierre-Olivier Mercier <nemunaire@nemunai.re>"
```
</div>
Dans notre `Dockerfile`, indiquez juste après l'image de base, vos noms,
prénoms et mails de contact avec l'instruction `LABEL maintainer`, pour
indiquer que c'est vous qui maintenez cette image, si des utilisateurs ont
prénoms et mails de contact avec l'instruction `LABEL maintainer`{.dockerfile},
pour indiquer que c'est vous qui maintenez cette image, si des utilisateurs ont
besoin de vous avertir pour le mettre à jour ou s'ils rencontrent des
difficultés par exemple.
@ -194,19 +194,19 @@ On le place dès le début, car comme c'est une information qui n'est pas amener
## Commande par défaut
Vous pouvez placer dans un `Dockerfile` une instruction `CMD` qui sera exécutée
si aucune commande n'est passée lors du `run`, par exemple :
Vous pouvez placer dans un `Dockerfile` une instruction `CMD`{.dockerfile} qui
sera exécutée si aucune commande n'est passée lors du `run`, par exemple :
<div lang="en-US">
```
CMD nginx -g "daemon off;"
```dockerfile
CMD nginx -g "daemon off;"
```
</div>
<div lang="en-US">
```
42sh$ docker image build --tag=my_nginx .
42sh$ docker container run -d -P my_nginx
```bash
42sh$ docker image build --tag=my_nginx .
42sh$ docker container run -d -P my_nginx
```
</div>
@ -238,23 +238,23 @@ plusieurs conteneurs, avant d'agréger le contenu compilé au sein du conteneur
final :
<div lang="en-US">
```
FROM gcc:4.9
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN gcc -static -static-libgcc -o hello hello.c
```dockerfile
FROM gcc:4.9
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN gcc -static -static-libgcc -o hello hello.c
FROM scratch
COPY --from=0 /usr/src/myapp/hello /hello
CMD ["/hello"]
FROM scratch
COPY --from=0 /usr/src/myapp/hello /hello
CMD ["/hello"]
```
</div>
Dans cet exemple, deux conteneurs distincts sont créés : le premier à partir de
l'image `gcc`, il contient tout le nécessaire pour compiler notre
`hello.c`. Mais l'image finale (le dernier `FROM` de notre `Dockerfile`) est
l'image vide, dans laquelle nous recopions simplement le produit de notre
compilation.
`hello.c`. Mais l'image finale (le dernier `FROM`{.dockerfile} de notre
`Dockerfile`) est l'image vide, dans laquelle nous recopions simplement le
produit de notre compilation.
L'image ainsi générée est minime, car elle ne contient rien d'autre que le
strict nécessaire pour s'exécuter.
@ -267,15 +267,15 @@ donner des noms à chaque image, plutôt que de devoir jongler avec les
numéros. Dans ce cas, on indiquera :
<div lang="en-US">
```
FROM gcc:4.9 as builder
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN gcc -static -static-libgcc -o hello hello.c
```dockerfile
FROM gcc:4.9 as builder
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN gcc -static -static-libgcc -o hello hello.c
FROM scratch
COPY --from=builder /usr/src/myapp/hello /hello
CMD ["/hello"]
FROM scratch
COPY --from=builder /usr/src/myapp/hello /hello
CMD ["/hello"]
```
</div>
@ -285,7 +285,7 @@ spécifiquement on souhaite construire avec l'option `--target` :
<div lang="en-US">
```
42sh$ docker build --target builder -t hello-builder .
42sh$ docker build --target builder -t hello-builder .
```
</div>
@ -301,7 +301,7 @@ Consultez <https://docs.docker.com/engine/reference/builder/> pour la liste
complète des instructions reconnues.
## Exercice
## Exercice {-}
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
@ -311,20 +311,15 @@ Pour réaliser ce genre de contribution, on ajoute généralement un `Dockerfile
à la racine du dépôt.
Vous pouvez cloner le dépôts de sources de `youp0m` à :
<div lang="en-US">
```
https://git.nemunai.re/youp0m.git
```
</div>
<https://git.nemunai.re/youp0m.git>
Pour compiler le projet, vous pouvez utiliser dans votre `Dockerfile`
<div lang="en-US">
```go
FROM golang:1.11
COPY . /go/src/git.nemunai.re/youp0m
WORKDIR /go/src/git.nemunai.re/youp0m
RUN go build -v
```dockerfile
FROM golang:1.11
COPY . /go/src/git.nemunai.re/youp0m
WORKDIR /go/src/git.nemunai.re/youp0m
RUN go build -v
```
</div>

View file

@ -9,8 +9,8 @@ Afin de faire bénéficier à nos utilisateurs d'une immersion parfaite, nous
allons faire en sorte que notre image permette d'être utilisée ainsi :
<div lang="en-US">
```
42sh$ docker run -d -p 80:80 youp0m -bind :80
```bash
docker run -d -p 80:80 youp0m -bind :80
```
</div>
@ -19,16 +19,17 @@ Plutôt que de laisser l'utilisateur se débrouiller avec le chemin interne dans
lequel il va trouver le bon binaire :
<div lang="en-US">
```
42sh$ docker run -d -p 80:80 youp0m /srv/youp0m -bind :80
```bash
docker run -d -p 80:80 youp0m /srv/youp0m -bind :80
```
</div>
Essayez les deux commandes, si vous avez utilisé l'instruction `CMD` dans votre
`Dockerfile` jusqu'à présent, vous devez vous trouver dans le deuxième cas.
Essayez les deux commandes, si vous avez utilisé l'instruction
`CMD`{.dockerfile} dans votre `Dockerfile` jusqu'à présent, vous devez vous
trouver dans le deuxième cas.
Pour améliorer la situation, définissez
l'[`ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint)
l'[`ENTRYPOINT`{.dockerfile}](https://docs.docker.com/engine/reference/builder/#entrypoint)
de votre image sur le binaire `/srv/youp0m`.
@ -43,26 +44,27 @@ Notre but, dans cette partie, sera de créer un utilisateur administrateur
(pouvant passer le contrôle d'accès <http://localhost:8080/admin/>) :
<div lang="en-US">
```
42sh$ docker run -i --rm -p 8080:8080 -e YOUP0M_PASSWORD=admin youp0m
```bash
docker run -i --rm -p 8080:8080 -e YOUP0M_PASSWORD=admin youp0m
```
</div>
### Bases du script
Notre script d'`ENTRYPOINT` sera appelé avec en argument, ceux passés par
l'utilisateur après le nom de l'image, ou, à défaut, le contenu de `CMD`.
Notre script d'`ENTRYPOINT`{.dockerfile} sera appelé avec en argument, ceux
passés par l'utilisateur après le nom de l'image, ou, à défaut, le contenu de
`CMD`.
C'est donc l'`ENTRYPOINT` qui est responsable de la bonne utilisation de
ceux-ci, de leur modification, ...
C'est donc l'`ENTRYPOINT`{.dockerfile} qui est responsable de la bonne
utilisation de ceux-ci, de leur modification, ...
À la fin d'un script d'`ENTRYPOINT`, afin de garder comme premier processus du
conteneur le programme qui nous intéresse, on réalise un `execve(2)`, sans
`fork(2)` :
À la fin d'un script d'`ENTRYPOINT`{.dockerfile}, afin de garder comme premier
processus du conteneur le programme qui nous intéresse, on réalise un
`execve(2)`, sans `fork(2)` :
<div lang="en-US">
```shell
exec /srv/youp0m $@
```bash
exec /srv/youp0m $@
```
</div>
@ -70,8 +72,8 @@ Dans cet exemple : `exec` est la commande interne à notre shell pour lui
indiquer de remplacer son fil d'exécution par cette commande (sans `exec`, il
va `fork(2)` avant). `$@` est ici pour transmettre tel quel la liste des
arguments passés au script (il s'agit de ceux donnés par l'utilisateur, sur la
ligne de commande du `run`, ou du contenu de `CMD` si l'utilisateur n'a rien
précisé).
ligne de commande du `run`, ou du contenu de `CMD`{.dockerfile} si
l'utilisateur n'a rien précisé).
### Format du fichier `htpasswd`
@ -80,12 +82,12 @@ Le format attendu est celui d'un fichier `htpasswd` typique d'Apache. Vous
pourriez obtenir un fichier valide avec :
<div lang="en-US">
```shell
(
echo -n "$YOUP0M_USERNAME"
echo -n ":"
openssl passwd -crypt "$YOUP0M_PASSWORD"
) > myhtpasswd
```bash
(
echo -n "$YOUP0M_USERNAME"
echo -n ":"
openssl passwd -crypt "$YOUP0M_PASSWORD"
) > myhtpasswd
```
</div>
@ -93,22 +95,23 @@ Il faut ensuite passer le fichier sur la ligne de commande grâce à l'option
`-htpasswd`.
### Exercice
### Exercice {-}
Écrivez un script d'`ENTRYPOINT`, analysant les variables d'environnement, à la
recherche de `YOUP0M_USERNAME` et `YOUP0M_PASSWORD` pour initialiser le fichier
`.htpasswd` qui sera ajouté à la liste des arguments à passer au service.
Écrivez un script d'`ENTRYPOINT`{.dockerfile}, analysant les variables
d'environnement, à la recherche de `YOUP0M_USERNAME` et `YOUP0M_PASSWORD` pour
initialiser le fichier `.htpasswd` qui sera ajouté à la liste des arguments à
passer au service.
Par exemple :
<div lang="en-US">
```
42sh$ docker run -d -p 8081:8081 -e YOUP0M_USERNAME=admin -e YOUP0M_PASSWORD=admin youp0m -bind=:8081
42sh$ docker run -d -p 8081:8081 -e YOUP0M_USERNAME=admin -e YOUP0M_PASSWORD=admin youp0m -bind=:8081
42sh$ curl -u admin:badpasswd http://localhost:8081/admin/
You are not allowed to perform this request.
42sh$ curl -u admin:badpasswd http://localhost:8081/admin/
You are not allowed to perform this request.
42sh$ curl -u admin:admin http://localhost:8081/admin/
<!DOCTYPE html>
42sh$ curl -u admin:admin http://localhost:8081/admin/
<!DOCTYPE html>
```
</div>

View file

@ -68,10 +68,10 @@ votre InfluxDB écoute sur le port 8086 local :
<div lang="en-US">
```bash
TELEGRAF_VERSION=1.8.0
wget https://dl.influxdata.com/telegraf/releases/telegraf-${TELEGRAF_VERSION}_linux_amd64.tar.gz
tar xf telegraf-${TELEGRAF_VERSION}_linux_amd64.tar.gz
TELEGRAF_CONFIG_PATH=./telegraf/etc/telegraf/telegraf.conf ./telegraf/usr/bin/telegraf
TELEGRAF_VERSION=1.8.0
wget https://dl.influxdata.com/telegraf/releases/telegraf-${TELEGRAF_VERSION}_linux_amd64.tar.gz
tar xf telegraf-${TELEGRAF_VERSION}_linux_amd64.tar.gz
TELEGRAF_CONFIG_PATH=./telegraf/etc/telegraf/telegraf.conf ./telegraf/usr/bin/telegraf
```
</div>
@ -82,16 +82,16 @@ Dans l'interface sélectionnez la base `telegraf` puis explorez les valeurs :
<div lang="en-US">
```sql
SHOW MEASUREMENTS
SHOW FIELD KEYS
SELECT usage_idle FROM cpu WHERE cpu = 'cpu-total' ORDER BY time DESC LIMIT 5
SHOW MEASUREMENTS
SHOW FIELD KEYS
SELECT usage_idle FROM cpu WHERE cpu = 'cpu-total' ORDER BY time DESC LIMIT 5
```
</div>
Laissons tourner `telegraf` afin de constituer un petit historique de valeurs.
## Rendu
## Rendu {-}
Avant de passer à la suite, placez votre `Dockerfile` et les éventuels fichiers
annexes dans un dossier `influxdb`.

View file

@ -55,10 +55,10 @@ vous codez.
Lorsqu'une ligne devient complexe, allez à la ligne :
<div lang="en-US">
```
RUN apt-get update && apt-get install -y \
nginx \
php5-fpm
```dockerfile
RUN apt-get update && apt-get install -y \
nginx \
php5-fpm
```
</div>
@ -70,13 +70,13 @@ Lorsque c'est possible, ordonnez vos lignes suivant un ordre logique. Par
exemple :
<div lang="en-US">
```
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
```dockerfile
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
```
</div>
@ -99,9 +99,9 @@ Il y a un certain nombre de règles à connaître pour bien utiliser ce mécanis
le(s) différente(s) image(s) qui dérive(nt) de la commande précédente. Si
aucune commande correspondante n'est trouvé, le cache se retrouve invalidé
pour les instructions suivantes.
- Pour les instructions `ADD` et `COPY`, en plus de la comparaison précédente,
la somme de contrôle du fichier est ajoutée. Si le fichier a été modifié, le
cache se retrouve invalidé.
- Pour les instructions `ADD`{.dockerfile} et `COPY`{.dockerfile}, en plus de
la comparaison précédente, la somme de contrôle du fichier est ajoutée. Si le
fichier a été modifié, le cache se retrouve invalidé.
- Une fois que le cache est invalidé, toutes les commandes restantes à exécuter
dans le `Dockerfile` vont être exécutées.
@ -132,10 +132,10 @@ lors de sa construction.
## Exposez les ports standards
La commande `EXPOSE` vous permet d'indiquer les ports sur lesquels votre
conteneur s'attend à recevoir des paquets venant de l'extérieur. Ces ports ne
sont pas partagés avec l'hôte ou les autres conteneur, donc vous n'avez pas de
raison de ne pas utiliser les ports standards.
La commande `EXPOSE`{.dockerfile} vous permet d'indiquer les ports sur lesquels
votre conteneur s'attend à recevoir des paquets venant de l'extérieur. Ces
ports ne sont pas partagés avec l'hôte ou les autres conteneur, donc vous
n'avez pas de raison de ne pas utiliser les ports standards.
Si vous faites cela, il y a de forte chance qu'il n'y ait pas besoin de
modifier la configuration des autres logiciels contenu dans d'autres conteneurs
@ -154,9 +154,9 @@ L'entrypoint peut être utilisé de deux manières différentes :
indiqué dans l'entrypoint. Par exemple pour nginx :
<div lang="en-US">
```
ENTRYPOINT ["nginx"]
CMD ["-g daemon off;"]
```dockerfile
ENTRYPOINT ["nginx"]
CMD ["-g daemon off;"]
```
</div>
@ -166,28 +166,29 @@ L'entrypoint peut être utilisé de deux manières différentes :
l'image de PostgreSQL possède cet entrypoint :
<div lang="en-US">
```shell
#!/bin/bash
set -e
```bash
#!/bin/bash
set -e
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
fi
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
fi
exec gosu postgres "$@"
fi
exec gosu postgres "$@"
fi
exec "$@"
exec "$@"
```
</div>
## `[""]`, `'` et sans `[]`
Les instructions `ENTRYPOINT` et `CMD` peuvent prendre deux formes :
Les instructions `ENTRYPOINT`{.dockerfile} et `CMD`{.dockerfile} peuvent
prendre deux formes :
- `["cmd", "arg1", "arg2"]` : ici, un simple `exexve` sera effectué avec ces
arguments. Si d'éventuels variables se trouve dans les arguments, elles ne
@ -201,14 +202,14 @@ pouvez pas utiliser les simple quotes.
## Volumes
L'instruction `VOLUME` doit être utilisée pour exposer tous les espaces de
stockage de données, configuration, ...
L'instruction `VOLUME`{.dockerfile} doit être utilisée pour exposer tous les
espaces de stockage de données, configuration,\ ...
## Réduisez les privilèges
Utilisez l'instruction `USER` dès que vous le pouvez, lorsqu'un service ne
réclame pas de privilège particulier.
Utilisez l'instruction `USER`{.dockerfile} dès que vous le pouvez, lorsqu'un
service ne réclame pas de privilège particulier.
Il vous faudra sans doute créer l'utilisateur et son groupe dans le Dockerfile.

View file

@ -6,8 +6,8 @@ Modification interactive
Pour créer une image, commençons par entrer dans un nouveau conteneur :
<div lang="en-US">
```
docker container run -it ubuntu /bin/bash
```bash
docker container run -it ubuntu /bin/bash
```
</div>
@ -19,8 +19,8 @@ afin de ne pas livrer de superflu, la liste des paquets et son cache ne sont
pas incluses dans le conteneur.
<div lang="en-US">
```
apt-get update
```bash
apt-get update
```
</div>
@ -33,8 +33,8 @@ jour.
Installons maintenant un programme :
<div lang="en-US">
```
apt-get install nano
```bash
apt-get install nano
```
</div>
@ -45,8 +45,8 @@ Sauvegardez vos modifications en tant que nouvelle image Docker, avec
la commande `commit` :
<div lang="en-US">
```
docker container commit CONTAINER my_nano
```bash
docker container commit CONTAINER my_nano
```
</div>
@ -57,8 +57,8 @@ doit servir de modèle. `my_nano` est le nom que vous voudrez utiliser
Testons sans plus attendre notre nouvelle image :
<div lang="en-US">
```
docker container run -it my_nano /bin/bash
```bash
docker container run -it my_nano /bin/bash
```
</div>

View file

@ -7,28 +7,28 @@ Projet
------
Avec l'aide d'un `Dockerfile` *multi-stage*, réalisez l'image la plus petite
possible (partant d'un `FROM scratch`), qui permette d'utiliser la [page de
compte à rebours](https://virli.nemunai.re/countdown.html) avec cette
possible (partant d'un `FROM scratch`{.dockerfile}), qui permette d'utiliser la
[page de compte à rebours](https://virli.nemunai.re/countdown.html) avec cette
configuration pour nginx :
<div lang="en-US">
```conf
events {}
events {}
http {
default_type text/html;
http {
default_type text/html;
index countdown.html;
index countdown.html;
server {
listen 8080;
server {
listen 8080;
root /srv/http;
root /srv/http;
rewrite "^/[0-9]+:[0-9]{2}$" /countdown.html;
rewrite "^/[0-9]+$" /countdown.html;
}
rewrite "^/[0-9]+:[0-9]{2}$" /countdown.html;
rewrite "^/[0-9]+$" /countdown.html;
}
}
```
</div>
@ -46,9 +46,9 @@ une attention particulière au suivi des bonnes pratiques d'écriture des
<div lang="en-US">
```
42sh$ docker build -t countdown countdown
42sh$ docker run -d -P countdown
42sh$ firefox http://localhost:32198/42:23
42sh$ docker build -t countdown countdown
42sh$ docker run -d -P countdown
42sh$ firefox http://localhost:32198/42:23
```
</div>
@ -83,15 +83,15 @@ supplémentaires) :
<div lang="en-US">
```
login_x-TP2/
login_x-TP2/youp0m/
login_x-TP2/youp0m/Dockerfile
login_x-TP2/youp0m/entrypoint.sh
login_x-TP2/youp0m/.dockerignore
login_x-TP2/youp0m/...
login_x-TP2/countdown/Dockerfile
(login_x-TP2/countdown/nginx.conf)
(login_x-TP2/countdown/countdown.html)
login_x-TP2/
login_x-TP2/youp0m/
login_x-TP2/youp0m/Dockerfile
login_x-TP2/youp0m/entrypoint.sh
login_x-TP2/youp0m/.dockerignore
login_x-TP2/youp0m/...
login_x-TP2/countdown/Dockerfile
(login_x-TP2/countdown/nginx.conf)
(login_x-TP2/countdown/countdown.html)
```
</div>

View file

@ -1,22 +1,24 @@
---
title: Virtualisation légère -- TP n^o^ 2.1
subtitle: Construire des images Docker
author: Pierre-Olivier *Nemunaire* Mercier
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA
date: Jeudi 18 octobre 2018
abstract: |
Durant ce deuxième TP, nous allons voir comment créer nos propres
images !
\vspace{1em}
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le mercredi 24 octobre 2018 à 0
h 42. Consultez la dernière section de chaque partie pour plus
d'information sur les éléments à rendre.
En tant que personnes sensibilisées à la sécurité des échanges
électroniques, vous devrez m'envoyer vos rendus signés avec votre
clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96)
faire signer votre clef et n'hésitez pas à [faire signer votre
clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
...
Durant ce deuxième TP, nous allons voir comment créer nos propres images !
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le mercredi 24 octobre 2018 à 0 h 42. Consultez la
dernière section de chaque partie pour plus d'information sur les éléments à
rendre.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
[faire signer votre clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
\tableofcontents

View file

@ -1,6 +1,20 @@
% Decent marging...
\usepackage[cm]{fullpage}
\addto\captionsfrench{
\renewcommand{\contentsname}
{Sommaire}
}
% Indentation for all paragraph (even the first one) + ventilate
\usepackage{indentfirst}
\setlength{\parskip}{6pt plus 2pt minus 1pt}
% Avoid vertical space before/after itemize
\usepackage{enumitem}
\setlist{nosep}
% Use sans-serif font for section' titles
\usepackage{sectsty}
\allsectionsfont{\sffamily \bfseries}
% Use monospaced font for URLs
\urlstyle{tt}
% In french, list item starts with dash, not bullet
\renewcommand\labelitemi{---}

View file

@ -20,9 +20,11 @@ La méthode la plus simple pour lancer un conteneur `lxc` est d'utiliser l'un de
ces modèles pour obtenir un nouveau système. On utilise pour cela la commande
`lxc-create` :
```
<div lang="en-US">
```bash
lxc-create --name toto_first --template debian
```
</div>
Ce modèle va créer un dossier dans `/var/lib/lxc/` (pouvant varier d'une
distribution à l'autre) portant le nom que nous avons précisé. Ce dossier va
@ -32,9 +34,11 @@ enfin le dossier `rootfs` contenant le système en lui-même.
Une fois l'installation terminée, on peut démarrer le conteneur :
```
<div lang="en-US">
```bash
lxc-start --name toto_first
```
</div>
`lxc` va appeler `/sbin/init` et démarrer tous les services que l'on peut
s'attendre à trouver dans n'importe quelle machine virtuelle (et même physique)
@ -59,9 +63,11 @@ Le modèle *Debian*, que nous avons utilisé, préremplit un fichier de
configuration sans définir de paramètre pour le réseau. Il n'y a donc pas
d'interface dans le conteneur pour le connecter :
```
<div lang="en-US">
```lxc
lxc.network.type = empty
```
</div>
Un excellent article détaillant les différents types de configuration réseau
est accessible à
@ -80,12 +86,14 @@ supplémentaire sur le réseau.
Modifions notre fichier de configuration afin qu'il ressemble à quelque chose
comme :
```
<div lang="en-US">
```lxc
lxc.network.type = macvlan
lxc.network.macvlan.mode = bridge
lxc.network.flags = up
lxc.network.link = eth0
```
</div>
Après avoir démarré le conteneur, il devrait avoir obtenu une IP du serveur
DHCP de l'école. L'inconvénient dans cette configuration est qu'il faille un
@ -101,11 +109,13 @@ plus flexible.
Voici un extrait de configuration correspondant au paramétrage d'une interface
virtuelle pour un conteneur donné :
```
<div lang="en-US">
```lxc
lxc.network.type = veth
lxc.network.ipv4 = 172.23.42.2/24
lxc.network.flags = up
```
</div>
Dans cette situation, au démarrage du conteneur, `lxc` va créer une interface
veth, avec un côté placé dans la machine hôte et l'autre côté placé dans le
@ -115,9 +125,11 @@ ensuite de configurer la machine hôte.
Commençons par attribuer une IP à cette nouvelle interface, en adaptant à votre
identifiant d'interface :
```
<div lang="en-US">
```bash
ip addr add 172.23.42.1/24 dev vethYJWD6R
```
</div>
À partir de là, nous devrions pouvoir pinger notre conteneur depuis notre
machine hôte : `ping 172.23.42.2`.
@ -129,9 +141,11 @@ via 10.0.0.0/8, le réseau de l'école.
Pour que notre machine hôte route les paquets, exécuter la commande :
```
<div lang="en-US">
```bash
sysctl -w net.ipv4.ip_forward=1
```
</div>
Cette variable, que nous retrouvons dans `/proc/sys/net/ipv4/ip_forward`,
indique au noyau qu'il peut faire passer les paquets réseau d'une interface à
@ -141,16 +155,20 @@ est une adresse privée, non routable sur Internet, ni même par le bocal. Il
faut donc ajouter une couche de NAT/PAT pour réécrire les adresses sources
avant d'envoyer les paquets sur internet :
```
<div lang="en-US">
```bash
iptables -t nat -A POSTROUTING ! -o vethYJWD6R -s 172.23.42.0/24 -j MASQUERADE
```
</div>
Dernière étape, dans notre conteneur, nous devons indiquer la route à utiliser
pour accéder à internet :
```
<div lang="en-US">
```bash
ip route add default via 172.23.42.1
```
</div>
Nous avons maintenant internet dans notre conteneur !
@ -159,18 +177,22 @@ Nous avons maintenant internet dans notre conteneur !
### Installation de InfluxDB
```
<div lang="en-US">
```bash
apt-get update
apt-get install wget
wget https://s3.amazonaws.com/influxdb/influxdb_0.9.4.2_amd64.deb
dpkg -i influxdb_0.9.4.2_amd64.deb
```
</div>
### Test de l'installation
<div lang="en-US">
```
/opt/influxdb/influxd
```
</div>
Une fois que le service est démarré, vous devriez pouvoir accéder à l'interface
à : <http://172.23.42.2:8083/>

16
tutorial/pandoc-opts.mk Normal file
View file

@ -0,0 +1,16 @@
PANDOCOPTS = --pdf-engine=xelatex \
--standalone \
--number-sections \
--toc \
-f markdown+smart \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
-M colorlinks=true \
-M linkcolor="black" \
-M urlcolor="ForestGreen" \
-M indent=true \
-V toc-title="Sommaire" \
--include-in-header=../header.tex