virli/tutorial/docker-basis/first.md

6.3 KiB

\newpage

Mon premier conteneur

Afin de tester la bonne marche de notre installation, lançons notre premier conteneur avec la commande :

``` docker container 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 store.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 Store, 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 Store en utilisant la commande pull :

``` docker image pull ubuntu ```

Remarquez comment on interagit avec chaque objet Docker : dans la ligne de commande, le premier mot clef est le type d'objet (container, image, service, network, volume, ...) ; ensuite, vient l'action que l'on souhaite faire dans ce cadre.1

Par exemple, 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 ls sous le type d'objets image :

``` docker image ls ```

Vous devriez constater la présence de plusieurs images « Ubuntu », mais chacune a un TAG différent. En effet, souvent, il existe plusieurs versions d'une même image. Pour Ubuntu par exemple, nous avons la possibilité de lancer la version trusty, xenial, zesty ou artful.

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é par défaut : latest. C'est le tag qui est automatiquement recherché lorsque l'on ne le précise 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 container 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.

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, vous pourriez tenter d'utiliser son gestionnaire de paquet apk, via :

``` docker container 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.

Images vs. conteneurs{ width=85% }

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 :

``` docker container run -it ubuntu /bin/bash ```

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 container run RUN_OPTS image IMAGE_CMD IMAGE_ARGS ... ```

Par exemple :

``` docker -H unix:///var/run/docker.sock container 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 transmis 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)). Nous demandons également l'allocation d'un TTY, sans quoi bash ne se lancera pas en mode interractif2.

TODO

TODO Nouvelle partie sur docker container ls


  1. cela n'a pas toujours été aussi simple, cette syntaxe n'existe que depuis la version 1.13 (janvier 2017). C'est pourquoi, lorsque vous ferez des recherches sur internet, vous trouverez de nombreux articles utilisant l'ancienne syntaxe, sans le type d'objets : docker images au lieu de docker image ls, docker run au lieu de docker container run, ...

    L'ancienne syntaxe est dépréciée, mais il reste actuellement possible de l'utiliser. ↩︎

  2. 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. ↩︎