tutorials: improve theme + use pandoc 2
This commit is contained in:
parent
de21be218a
commit
d25af4fdb2
65 changed files with 1281 additions and 1292 deletions
|
@ -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
|
||||
|
|
|
@ -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 :
|
||||
|
||||
|
|
|
@ -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 !
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 :
|
||||
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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)`.
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)`.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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 :
|
||||
|
||||
|
||||

|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 !
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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` ;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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{---}
|
||||
|
|
|
@ -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
16
tutorial/pandoc-opts.mk
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue