2016-09-08 01:44:20 +00:00
|
|
|
\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
|
2016-09-08 02:40:34 +00:00
|
|
|
`hub.docker.com`. Ce site met à disposition un grand nombre d'images : des
|
2016-09-08 01:44:20 +00:00
|
|
|
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
|
|
|
|
```
|
|
|
|
|
2017-10-04 07:00:58 +00:00
|
|
|
Vous devriez constater la présence de plusieurs images « Ubuntu », mais chacune
|
|
|
|
a un *TAG* différent. En effet, souven, il existe plusieurs versions d'une même
|
|
|
|
image. Pour Ubuntu par exemple, nous avons la possibilité de lancer la version
|
|
|
|
`precise`, `trusty`, `xenial` ou `yakkety`.
|
2016-09-08 01:44:20 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2017-10-04 07:00:58 +00:00
|
|
|
Pour nous en convaincre, nous pouvons tenter d'exécuter un programme qui n'est
|
|
|
|
pas présent sur notre machine, mais bien uniquement dans le conteneur. Si vous
|
|
|
|
n'utilisez pas [Alpine Linux](https://www.alpine-linux.org), vous pourriez
|
|
|
|
tenter d'utiliser son gestionnaire de paquet `apk`, via :
|
2016-09-08 01:44:20 +00:00
|
|
|
|
2017-10-04 07:00:58 +00:00
|
|
|
```
|
|
|
|
docker run alpine /sbin/apk stats
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Modifier une image
|
|
|
|
|
|
|
|
### Images vs. conteneurs
|
|
|
|
|
|
|
|
À chaque fois que nous lançons un `run`, un nouveau conteneur est créé.
|
|
|
|
L'image fournie comme argument est utilisée comme un modèle de base pour le
|
|
|
|
conteneur et est recopiée grâce à un mécanisme de *Copy-On-Write* : c'est donc
|
|
|
|
très rapide et ne consomme pas beaucoup d'espace disque.
|
|
|
|
|
|
|
|
Étant donné que chaque conteneur est créé à partir d'un modèle, 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.
|
2016-09-08 01:44:20 +00:00
|
|
|
|
2017-10-04 07:00:58 +00:00
|
|
|
![Images vs. conteneurs](img-vs-cntr.png "Images vs. conteneurs")
|
2016-09-08 01:44:20 +00:00
|
|
|
|
2017-10-04 07:00:58 +00:00
|
|
|
Dans ce schéma, on considère les images comme étant la partie figée de Docker à
|
|
|
|
partir desquelles on peut créer des conteneurs.
|
|
|
|
|
|
|
|
Si l'on souhaite qu'une modification faite dans un conteneur (par exemple
|
|
|
|
l'installation d'un paquet) s'applique à d'autres conteneurs, il va falloir
|
|
|
|
créer une nouvelle image à partir de ce conteneur.
|
|
|
|
|
|
|
|
|
|
|
|
### Les paramètres
|
|
|
|
|
|
|
|
Pour créer une image, commençons par entrer dans un nouveau conteneur :
|
2016-09-08 01:44:20 +00:00
|
|
|
|
|
|
|
```
|
|
|
|
docker run -it ubuntu /bin/bash
|
|
|
|
```
|
|
|
|
|
2017-10-04 07:00:58 +00:00
|
|
|
Vous avez remarqué l'utilisation des options `--tty` et `--interactive` ? Avant
|
|
|
|
le nom de l'image, elles sont gérées par Docker pour modifier le comportement
|
|
|
|
du `run`. En fait, tout comme `git(1)` et ses sous-commandes, chaque niveau de
|
|
|
|
commande peut prendre des paramètres :
|
|
|
|
|
|
|
|
```
|
|
|
|
docker DOCKER_PARAMS run RUN_OPTS image IMAGE_CMD IMAGE_ARGS ...
|
|
|
|
```
|
|
|
|
|
|
|
|
Par exemple :
|
|
|
|
|
|
|
|
```
|
|
|
|
docker -H unix:///var/run/docker.sock run -it alpine /bin/ash -c "echo foo"
|
|
|
|
```
|
|
|
|
|
|
|
|
Ici, l'option `-H` sera traitée par le client Docker (pour définir
|
|
|
|
l'emplacement du point de communication avec le daemon), tandis que les options
|
|
|
|
`-it` seront utilisées lors du traitement du `run`. Quant au `-c`, il sera
|
|
|
|
simplement tranmis au conteneur comme argument au premier `execve(2)` du
|
|
|
|
conteneur.
|
|
|
|
|
|
|
|
Avec l'option `--interactive`, on s'assure que l'entrée standard ne sera pas
|
|
|
|
fermée (`close(2)`)[^whyclose]. Nous demandons également l'allocation d'un TTY,
|
|
|
|
sans quoi `bash` ne se lancera pas en mode interractif[^bashnointer].
|
|
|
|
|
|
|
|
[^whyclose]: TODO
|
|
|
|
|
|
|
|
[^bashnointer]: Mais il sera possible de l'utiliser sans allouer de TTY, comme
|
|
|
|
par exemple en faisant :
|
|
|
|
|
|
|
|
```
|
|
|
|
42sh$ cat cmd
|
|
|
|
echo foo
|
|
|
|
42sh$ cat cmd | docker run -i busybox
|
|
|
|
foo
|
|
|
|
```
|
|
|
|
|
|
|
|
L'option `-i` reste néanmoins nécessaire pour que l'entrée standard soit
|
|
|
|
transmise au conteneur.
|
|
|
|
|
|
|
|
|
|
|
|
### Modification interractive
|
|
|
|
|
|
|
|
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
|
2016-09-08 01:44:20 +00:00
|
|
|
`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` !
|