Ready for j1

This commit is contained in:
nemunaire 2016-09-08 03:44:20 +02:00
parent 150f5a8834
commit dc8544c0c9
31 changed files with 688 additions and 544 deletions

View file

@ -1,13 +1,16 @@
SOURCES = tutorial.md installation.md lxc.md cgroups.md namespaces.md
TEMPLATE = ../../template.tex
SOURCES = tutorial.md installation.md what.md first.md dockerfile.md volumes.md linking.md cleaning.md rendu.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=frenchb \
-M fontsize=12pt \
-M papersize=a4paper \
--template=${TEMPLATE}
-M mainfont="Linux Libertine O" \
-M monofont="Inconsolata" \
-M sansfont="Linux Biolinum O" \
--include-in-header=../header.tex
all: tutorial.pdf

47
tutorial/1/cleaning.md Normal file
View file

@ -0,0 +1,47 @@
\newpage
Faire le ménage
===============
Au fur et à mesure de vos tests, la taille utilisée par les données de Docker
peut devenir conséquente et son interface peut commencer à déborder
d'informations dépréciées.
Dans la mesure du possible, Docker essaie de ne pas encombrer inutilement votre
disque dur avec les vieilles images qui ne sont plus utilisées. Il ne va
cependant jamais supprimer une image encore lié à un conteneur, ni les
conteneurs qui n'auront pas été démarrés avec `--rm`.
## Conteneurs
Vous pouvez afficher l'ensemble des conteneurs, quelque soit leur état (en
cours d'exécution, arrêté, ...) avec la commande suivante :
```
42sh$ docker ps -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
```
IL y a de fortes chances pour que vous n'ayez plus besoin de ces vieux
conteneurs. Pour les supprimer, utilisez la commande :
```
docker rm 0e8bbff6d500 552d71619723
```
ou encore :
```
docker rm cranky_jones dreamy_gates
```
## Images
Les vieilles images qui n'ont plus de références sur elles (ni tag, ni
conteneur lié) sont automatiques supprimées. Vous n'avez généralement pas à
vous occuper de faire du nettoyage dans les images. Néanmoins, vous pouvez les
lister avec la commande `docker images` et en supprimer grâce à la commande
`docker rmi`.

View file

@ -1,6 +1,7 @@
\newpage
# `Dockerfile`
`Dockerfile`
============
## Mon premier conteneur ... par `Dockerfile`
@ -42,8 +43,10 @@ docker run -it my_editor /bin/bash
## `RUN` dans le `Dockerfile`
Chaque ligne est exécutée indépendamment des autres ;
cela signifie que l'exemple suivant **ne fonctionne pas** :
Dans un `Dockerfile`, chaque ligne est exécutée indépendamment des
autres et correspondra à une nouvelle couche de notre image.
Cela signifie que l'exemple suivant **ne fonctionne pas** :
```
COPY db.sql /db.sql

145
tutorial/1/first.md Normal file
View file

@ -0,0 +1,145 @@
\newpage
Mon premier conteneur
=====================
Afin de tester la bonne marche de votre installation, exécutons la commande :
```
docker run hello-world
```
Cette commande va automatiquement exécuter une série de commandes pour nous,
comme indiqué dans le message affiché en retour :
D'abord, le daemon va rechercher s'il possède localement l'image
*hello-world*. Si ce n'est pas le cas, il va aller la récupérer sur
<hub.docker.com>. Ce site met à disposition un grand nombre d'images : des
systèmes de base comme Ubuntu, Debian, Centos, etc. jusqu'à des conteneurs
prêts à l'emploi : le serveur web nginx, la base de données MySQL, un serveur
node.js, etc.
Nous pouvons directement utiliser le client pour rechercher une image sur le
hub, en utilisant la commande `search` :
```
docker search mariadb
```
Il est possible de mettre à jour les images locales ou simplement
pré-télécharger des images depuis le hub en utilisant la commande `pull` :
```
docker pull ubuntu
```
Pour consulter la liste des images dont nous disposons localement (soit parce
qu'on les a téléchargées, soit parce que nous les avons créées nous-même), on
utilise la commande `images` :
```
docker images
```
Nous devrions constater la présence de deux images « Ubuntu », ayant un *TAG*
différent. Souvent, il existe plusieurs versions d'une même image. Pour Ubuntu
par exemple, nous avons la possibilité de lancer la version `vivid`, `trusty`
ou `precise`.
Chaque image est identifiable par son *Image ID* unique ; les noms d'images
ainsi que leurs tags sont, comme les tags Git, une manière humainement plus
simple de faire référence aux identifiants.
Chaque nom d'image possède au moins un tag associé : *latest*. C'est le tag qui
est automatiquement recherché lorsque l'on ne le précisez pas en lançant
l'image.
## Exécuter un programme dans un conteneur
Maintenant que nous avons à notre disposition l'image d'un conteneur Ubuntu,
lançons-la !
La commande `run` de Docker prend comme derniers arguments le programme à
lancer dans le conteneur ainsi que ses éventuels arguments. Essayons d'afficher
un Hello World :
```
docker run ubuntu /bin/echo "Hello World"
```
Dans notre exemple, c'est bien le `/bin/echo` présent dans le conteneur qui est
appelé. Ce n'est pas le programme `/bin/echo` de la machine hôte qui a été
transféré dans le conteneur.
## Modifier un conteneur
À chaque fois que nous lançons un `run`, un nouveau conteneur est créé à partir
de l'image que l'on a précisé (via un mécanisme de Copy-On-Write, c'est donc
très rapide et ne consomme pas beaucoup d'espace disque). Cela signifie que
lorsque nous exécutons une commande modifiant les fichiers d'un conteneur, cela
ne modifie pas l'image de base, mais crée une nouvelle image. Que nous pouvons
ensuite utiliser comme image de base.
Commençons par entrer dans un nouveau conteneur pour modifier l'image :
```
docker run -it ubuntu /bin/bash
```
Nous voilà maintenant dans le conteneur ! Il est assez épuré, il n'y a rien de
superflu : il n'y a même pas d'éditeur de texte : ni vim, ni emacs, même pas
`vi` !
La première chose à faire est de télécharger la liste des paquets. En effet,
afin de ne pas livrer de superflu, la liste des paquets et son cache ne sont
pas inclues dans le conteneur.
```
apt-get update
```
Il peut arriver que des paquets présents dans l'image ne soient pas à
jour. Afin de garder un environnement cohérent, il est recommandé de ne pas
utiliser le gestionnaire de paquets pour mettre à jour les paquets présent de
base, mais plutôt de contacter le mainteneur de l'image pour qu'il la mette à
jour.
Installons maintenant un programme :
```
apt-get install nano
```
En attendant la fin de l'installation, jetons un œil à la commande dans un
autre terminal :
```
docker ps
```
Cette commande liste les conteneurs actifs. Notez le *Container ID* ainsi que
le *NAMES* du conteneur du conteneur actuellement en cours d'installation de
`nano`.
Lorsque l'installation de `nano` est terminée, quittez l'image en tapant
`exit`.
Sauvegardez votre image modifiée avec la commande `commit` pour pouvoir
commencer directement de votre image avec `nano` :
```
docker commit CONTAINER my_nano
```
En remplaçant `CONTAINER` par le nom ou l'identifiant de votre
container. `my_nano` est le nom que vous voudrez utiliser à la place
d'`ubuntu` :
```
docker run -it my_nano /bin/bash
```
Vous constatez cette fois que vous pouvez lancer `nano`, alors que vous ne
pouvez toujours pas le faire dans un conteneur issue d'une image `ubuntu` !

View file

@ -1,55 +1,107 @@
\newpage
# Installation
Installation
============
## Noyau Linux
## Prérequis
Ce TP requiert un noyau Linux 3.8 au minimum. De plus, il doit être
compilé avec les options suivantes :
Docker repose sur plusieurs techniques implémentés dans les récents noyaux
Linux. Nous consacrerons les prochains cours à comprendre leurs
fonctionnement. Ces techniques ne sont pas limitées à une architecture de
microprocesseur spécifique (comme peuvent l'être les instructions de
virtualisation nécessaire pour rendre les hyperviseurs attractifs) ; cependant
la communauté autour de Docker utilisant principalement l'architecture `amd64`,
c'est sur cette dernière que Docker pourra être exploité à son plein potentiel.
Avant de continuer, assurez-vous que votre machine a bien démarré sur un noyau
64 bits. Le retour de la commande `uname -m` doit vous indiquer :
```
General setup --->
[*] Control Group support --->
[*] Freezer cgroup subsystem
[*] Device controller for cgroups
[*] Cpuset support
[*] Include legacy /proc/<pid>/cpuset file
[*] Simple CPU accounting cgroup subsystem
[*] Group CPU scheduler --->
[*] Group scheduling for SCHED_OTHER
[*] Group scheduling for SCHED_RR/FIFO
<*> Block IO controller
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace
[*] PID Namespaces
[*] Network namespace
[*] Networking support --->
Networking options --->
<*> 802.1d Ethernet Bridging
<M> 802.1Q VLAN Support
[*] Network priority cgroup
[*] Network classid cgroup
Device Drivers --->
[*] Network device support --->
<M> MAC-VLAN support
<*> Virtual ethernet pair device
Character devices --->
-*- Unix98 PTY support
[*] Support multiple instances of devpts
x86_64
```
Une fois que vous aurez installé LXC, vous pouvez vérifier la compatibilité de
la configuration de votre noyau en utilisant la commande `lxc-checkconfig`.
Assurez-vous également d'avoir un noyau récent, avec la commande `uname -r` :
```
4.7.2-gentoo
```
Vous ne pourrez pas utiliser Docker avec un noyau antérieur à la version 3.10.
## LXC
## Par le gestionnaire de paquets
Pour installer LXC, utilisez le gestionnaire de paquets de votre
distribution. Toute les bonnes distributions fournissent un paquet
`lxc`. Vérifiez que la version installée est au moins la 1.0.
En général, votre distribution mettra à votre disposition une version de Docker
plus ou moins récente. Sous Debian et ses dérivés (Ubuntu, Mint, ...) le paquet
a été nommé `docker.io`.
Aucune configuration ne devrait vous être demandé durant l'installation. Une
fois installé, exécutez la commande `lxc-checkconfig` pour vérifier que votre
noyau possède bien toutes les options nécessaires.
Si dans un environnement de production, on préférera sans doute utiliser une
version déjà bien éprouvée, pour ce cours, nous allons avoir besoin de la
dernière version disponible :
<https://docs.docker.com/engine/installation/linux/>
Installez également le paquet `docker-compose`.
## Vérifier la bonne marche de l'installation
Vous devriez maintenant être capable de lancer la commande suivante :
```
docker version
```
Une sortie similaire au bloc suivant devrait apparaître sur votre écran :
```
Client:
Version: 1.12.1
API version: 1.24
Go version: go1.7
Git commit: 23cf638
Built:
OS/Arch: linux/amd64
Server:
Version: 1.12.1
API version: 1.24
Go version: go1.7
Git commit: 23cf638
Built:
OS/Arch: linux/amd64
```
### `no such file or directory`?
Si vous avez cette erreur : `dial unix /var/run/docker.sock: no such file or
directory.`, le deamon n'est sans doute pas lancé. Lancez-le :
```
sudo service docker restart
```
### `permission denied`?
Si vous avez cette erreur : `dial unix /var/run/docker.sock: permission
denied.`, ajoutez votre utilisateur au groupe `docker` et **relancer votre
session** :
```
sudo gpasswd -a $USER docker
```
**Attention :** cette action n'est pas anodine d'un point de vue sécurité :
<https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface>
## Rendu
### Questions
1. Dans quel langage Docker a-t-il été écrit ?
1. Décrivez une méthode permettant à un utilisateur (non-root), présent dans le
groupe `docker`, d'effectuer une action privilégiée impactant la machine
hôte.

View file

@ -1,6 +1,7 @@
\newpage
## Lier les conteneurs
Lier les conteneurs
===================
En plus de vouloir partager des répertoires entre deux conteneurs, il est
souvent nécessaire de partager des ports.
@ -20,7 +21,7 @@ docker run -e MYSQL_ROOT_PASSWORD=mysecretpassword -d --name db1 mysql
docker run --link db1 my_nginx
```
### Ambasador
## Ambasador
Afin d'abstraire le plus possible l'infrastructure sous-jacente et d'autoriser
les migrations de conteneurs, on utilise le modèle *ambassador*.

114
tutorial/1/rendu.md Normal file
View file

@ -0,0 +1,114 @@
\newpage
Sujet à rendre
==============
## Projet
Écrivez un `Dockerfile` pour conteneriser un client netsoul.
Vous pouvez utiliser le client de votre choix, comme par exemple
[tumsoul.py](https://virli.nemunai.re/misc/tumsoul_0.3.3.py).
Une fois construit, le conteneur doit se lancer comme cela :
```
docker run -e NETSOUL_LOGIN="login_x" -e PASSSOCKS="xnigol42" netsoul
```
Passer la configuration d'un conteneur dans des variables d'environnement est
une méthode couramment utilisée. Ces variables sont récupérées et traitées par
le script d'ENTRYPOINT. Ce qui permet d'utiliser la ligne de commande pour
d'autres choses.
## Modalité de rendu
Un service automatique s'occupe de réceptionner vos rendus, de faire les
vérifications nécessaires et de vous envoyer un accusé de réception (ou de
rejet).
Ce service écoute sur l'adresse <virli@nemunai.re>, c'est donc à cette adresse
et exclusivement à celle-ci que vous devez envoyer vos rendus. Tout rendu
envoyé à une autre adresse et/ou non signé ne sera pas pris en compte.
## Tarball
Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...).
Les réponses aux questions sont à regrouper dans un fichier `questions.txt` à
placer à la racine de votre rendu.
Voici une arborescence type:
```
login_x-TP1/questions.txt
login_x-TP1/webserver
login_x-TP1/webserver/Dockerfile
login_x-TP1/webserver/index.html
login_x-TP1/webserver/datavolume-run.sh
login_x-TP1/netsoul
login_x-TP1/netsoul/Dockerfile
login_x-TP1/netsoul/docker-entrypoint.sh
login_x-TP1/netsoul/tumsoul.py
```
## Signature du rendu
Deux méthodes sont utilisables pour signer votre rendu :
* signature du courriel ;
* signature de la tarball.
Dans les deux cas, si vous n'en avez pas déjà une, vous devrez créer une clef
PGP à votre nom et prénom.
Pour valider la signature, il est nécessaire d'avoir reçu la clef publique
séparément. Vous avez le choix de l'uploader sur un serveur de clefs, soit de
me fournir votre clef en main propre, soit l'envoyer dans un courriel distinct.
### Signature du courriel
[Enigmail](https://enigmail.net) est une extension très bien réputée pour
signer ses mails depuis Thunderbird.
Utilisez le service automatique <signcheck@nemunai.re> pour savoir si votre
courriel est correctement signé et que je suis en mesure de vérifier la
signature.
### Astuces
#### No public key
Si vous recevez un rapport avec l'erreur suivante :
```
[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
```
C'est que votre clef publique n'est pas dans mon trousseau et que les méthodes
de récupérations automatiques n'ont pas permis de la trouver. Uploadez votre
clef sur un serveur de clefs (et attendez quelques minutes sa propagation) ou
envoyez un courriel avec votre clef publique en pièce-jointe, avant de retenter
votre rendu.
#### Not explicit username
Si vous recevez un rapport avec l'erreur suivante :
```
[FAIL] The username of your key is not explicit, I can't find you.
```
Votre clef ne contient sans doute pas vos noms et prénoms ou l'adresse
électronique associée à la clef n'est pas celle que j'ai dans ma base de
données.

View file

@ -1,21 +1,27 @@
% Virtualisation légère -- TP n^o^ 1
% Pierre-Olivier *nemunaire* Mercier
% Jeudi 8 octobre 2015
---
title: Virtualisation légère -- TP n^o^ 1
subtitle: Les bases de Docker
author: Pierre-Olivier *Nemunaire* Mercier
institute: EPITA
date: Jeudi 8 septembre 2016
...
Le but de ce premier TP est d'utiliser les commandes et les appels systèmes vu
durant le cours.
Durant ce premier TP, nous allons apprendre à utiliser Docker !
Tous les éléments de ce TP (exercices et questions) sont à rendre à
<virli@nemunai.re> au plus tard le **mercredi 21 octobre 2015 à 23
h 42**. Consultez la dernière section de chaque partie pour plus d'information
sur les éléments à rendre. Vous pouvez placer les réponses aux questions dans
le corps du courriel ou dans un fichier texte joint.
<virli@nemunai.re> au plus tard le jeudi 15 septembre 2016 à 8 h 42. Consultez la
dernière section de chaque partie pour plus d'information sur les éléments à
rendre. Vous pouvez placer les réponses aux questions dans le corps du courriel
ou dans un fichier joint.
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devriez m'envoyer vos rendus signés avec votre clef PGP. Pensez à
[me](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
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](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96)
faire signer votre clef et n'hésitez pas à
[faire signer votre clef](http://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
Vous pouvez utiliser l'adresse <signcheck@nemunai.re> pour savoir si
vous vous y prenez correctement.
\hypersetup{linkcolor=black}
\tableofcontents

View file

@ -1,6 +1,7 @@
\newpage
## Volumes
Volumes
=======
Il est possible de partager des répertoires entre plusieurs conteneurs. Pour ce
faire, il faut déclarer dans le `Dockerfile` une ou plusieurs instructions
@ -38,7 +39,7 @@ Une lecture intéressante sur ce sujet est sans doute [cet article de Michael
Crosby](http://crosbymichael.com/advanced-docker-volumes.html).
### Partage avec la machine hôte
## Partage avec la machine hôte
Il est possible de monter un répertoire de la machine hôte dans un
conteneur. L'intérêt reste plutôt limité à des fins de facilité ou de test, par
@ -54,7 +55,7 @@ Une fois cette commande lancée, votre voisin pourra accéder à votre dossier
Downloads en renseignant l'IP de votre machine dans son navigateur favori !
### Data Volume Container
## Data Volume Container
Dans de nombreuses situations, il est intéressant de séparer les données de
l'application, et donc d'avoir un conteneur exécutant l'application et un
@ -111,4 +112,4 @@ vie !
terminal pour créer le *data volume container*, construire l'image à partir du
Dockerfile et lancer le conteneur `my_webserver` lié.
Rendre le Dockerfile, son contexte et le script de construction/lancement.
Rendre le `Dockerfile`, son contexte et le script de construction/lancement.

84
tutorial/1/what.md Normal file
View file

@ -0,0 +1,84 @@
\newpage