Ready for j1

This commit is contained in:
nemunaire 2016-09-08 03:44:20 +02:00
commit dc8544c0c9
31 changed files with 690 additions and 546 deletions

View file

@ -1,182 +1,85 @@
\newpage
# Mon premier conteneur
# Premiers pas
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.
Dans un premier temps, nous allons créer une image Docker comme si
l'on réalisait l'installation sur une machine classique : en suivant
une recette. La machine (notre première image Docker) contient tout le
nécessaire pour faire fonctionner notre service.
## Exécuter un programme dans un conteneur
## Les caches
Maintenant que nous avons à notre disposition l'image d'un conteneur Ubuntu,
lançons-la !
Nous avons vu que chaque instruction de notre `Dockerfile` génère une
couche. Chaque couche sert de cache d'une construction de conteneur à
l'autre. Ainsi, lorsque vous modifiez une instruction dans votre
`Dockerfile`, les instructions précédentes ne sont pas réexécutées
mais sont ressorties du cache.
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 :
Le cache se basant principalement sur le contenu de chaque instruction
dans le `Dockerfile` (pour les `COPY` et `ADD`, il va aussi regarder
la date de dernière modification de fichier copié ou ajouté). Donc
tant qu'une instruction n'est pas modifiée dans le `Dockerfile`, le
cache sera utilisé.
```
docker run ubuntu /bin/echo "Hello World"
```
Il est possible de ne pas utiliser le cache et de relancer toutes les
étapes du `Dockerfile` en ajoutant l'option `--no-cache` au moment du
`docker build`.
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.
Les couches du cache peuvent être partagées entre plusieurs conteneur,
c'est ainsi que vous pouvez partager facilement une plus grosse partie
du système de fichier (afin de profiter du cache du système de
fichiers au moment de l'exécution du conteneur).
## Modifier un conteneur
## `apt-get`
À 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.
Pour profiter du cache, il faut donc placer les étapes les plus
génériques (qui seraient susceptibles d'apparaître dans plusieurs
conteneur), en haut du `Dockerfile`.
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` !
Commençons donc notre `Dockerfile` : choisissez une image de base pour
votre `FROM`, et indiquez votre nom avec l'instruction `MAINTAINER`,
pour indiquez que c'est vous qui maintenez ce conteneur (si d'autres
gens ont besoin qu'il faut le mettre à jour par exemple).
## Métadonnées
## `RUN` ou script ?
Les images et les conteneurs sont composés d'un ensemble de couches de système
de fichiers et de métadonnées. Ces métadonnées stockent de nombreux paramètres
tels que la commande à lancer par défaut pour une image, ou le PID du premier
programme lancé pour un conteneur.
### InfluxDB
Vous pouvez affichez ces métadonnées avec la commande `docker inspect
hello-world`.
Ensuite viens l'installation d'InfluxDB. Le paquet n'est pas
disponible dans les dépôts. La
[https://influxdb.com/docs/v0.9/introduction/installation.html](procédure
décrite sur le site) incite à télécharger le paquet mis à disposition
puis à l'installer via `dpkg -i`.
Deux solutions s'offrent à nous : télécharger le paquet hors du
conteneur, le copier, puis l'installer. Ou faire un `RUN` avec toutes
ces opérations (sans oublier l'installation de `wget`/`curl`).
La copie étant définitive (supprimer le fichier ne le supprimera pas
des couches où il a pu exister), donc la seconde solution semble
préférable (mais `wget` restera en déchet).
Écrivez une commande `RUN` qui va télécharger la dernière version
d'InfluxDB, qui va l'installer et supprimer le fichier.
\vspace{1em}
À ce stade, nous pouvons déjà terminer le conteneur et tester
qu'InfluxDB est bien utilisable : `EXPOSE`, `CMD`, ... Il est possible
que vous ayez à écraser le fichier de configuration via un
`COPY`. Garder la ligne qui vous permet de lancer votre serveur web
dans un coin, en attendant la partie suivante.
## Rendu
### Grafana
### Questions
Une fois InfluxDB configuré, nous allons avoir la même réflexion avec
Grafana.
1. Comment limiter la quantité maximale de mémoire qu'un conteneur pourra
utiliser ?
De la même manière, téléchargez, installez et supprimez le paquet.
1. Un conteneur Docker se détache-t-il de tous les *namespaces* ? Si non,
pourquoi ?
### Exercice
Réalisez un script permettant de rejoindre les namespaces d'un conteneur Docker
actif. Vous pouvez réutiliser votre exécutable `setns` du premier TP. Vous
allez sans doute avoir besoin d'utiliser `docker inspect`, n'hésitez pas à
consulter son aide : `docker inspect --help`.
```
host# ./docker-attach romantic_archimedes /bin/bash
inCntnr# _
```
`romantic_archimedes` correspond au nom du conteneur Docker auquel on veut
s'attacher et `/bin/bash`, la première commande que l'on va exécuter après le
`clone`.
Lors de vos tests, sachez que vous pouvez vous connecter sur grafana avec
l'utilisateur *admin*, mot de passe *admin*.