Créer, utiliser et supprimer une image

Dans l'article d'introduction à docker nous avons vu que toute image docker est créée à partir d'un fichier Dockerfile. Ce fichier Dockerfile est composé d'un ensemble d'instructions et arguments qui vont nous permettre de créer l'environnement nécessaire au bon fonctionnement de notre environnement.

Savoir écrire un fichier Dockerfile est primordiale et nous verrons comment le faire mais avant cela il est nécessaire de voir comment créer et utiliser une image. Pour cela nous allons partir du Dockerfile du projet Dirsearch écrit en python3 par maurosoria. Le projet est disponible ici https://github.com/maurosoria/dirsearch.

Voici le contenu du Dockerfile:

FROM python:3
MAINTAINER greenmind.sec@gmail.com
RUN apt-get update -y
RUN apt-get install python3-pip -y
WORKDIR /root
ADD . .
WORKDIR /root/
RUN chmod +x dirsearch.py
ENTRYPOINT ["/root/dirsearch.py"]
CMD ["--help"]

Pour créer une image à partir d'un Dockerfile il suffit d'entrer cette commande:

sudo docker build <nom_dockerfile> -t <nom_de_l'image:numéro_de_version>

A ce moment là un ensemble d'opérations vont être réalisées en fonction des instructions présentes dans le Dockerfile. Une fois le build terminé nous pourrons voir qu'une nouvelle image est disponible. Pour cela il faudra lancer la commande :

sudo docker images

Ici on peut voir que l'image dirsearch dans sa version 0.3.8 a été créée il y a deux minutes, possède l'identifiant d'image daf2dac4a280 et pèse 1,08 Go. Une fois l'image créée nous pourrons la lancer ce qui créera automatiquement un container. Pour cela il faudra utiliser cette commande:

sudo docker run "dirsearch:0.3.8"

Il est aussi possible de lancer une image directement depuis son image ID.

Et voici l'output:

On reviendra un peu plus tard sur cet output. En exécutant la commande précédente nous avons créer un container. Nous pouvons d'ailleurs voir la liste des containers existants en tapant la commande suivante:

sudo docker container ls -a

Encore une fois, un container est identifié par un CONTAINER ID ainsi que l'ID de l'image qu'il utilise. Un container est à un instant T dans un des états suivants:

  • created: le container existe mais n'est pas utilisé
  • restarting: le container redémarre
  • running: le container est en cours d'utilisation
  • paused: le container n'est pas en cours d'utilisation
  • exited: le container n'est plus utilisé
  • dead: un container dans l'état dead est un container qui est probablement cassé suite à une erreur de configuration.

Dans notre cas le container est dans l'état "Exited" car le processus principal s'est terminé ce qui se conclue par un return 0 indiqué après le status du container.

Pour plusieurs raisons il nous arrivera de vouloir supprimer une image de notre base de données locale. Pour cela on pourra utiliser cette commande:

sudo docker rmi "nom_de_l'image:version_de_l'image"

On pourra aussi supprimer une image à partir de son image ID.

Ah, que c'est-il passé? Comme nous l'avons vu plus tôt, lorsque nous avons lancé l'image dirsearch:0.3.8 un container a été créé. Ce container a exécuté le processus principal puis s'est arrêté. Actuellement il est dans l'état Exited. Pour pouvoir supprimer une image il faut qu'il n'y ait aucun container existant (peu importe l'état de ce dernier) dans notre liste de container. Or nous en avons toujours un d'existant. Il va donc falloir le supprimer avant de supprimer l'image.

Pour cela il faudra entrer ces commandes:

sudo docker rm <nom_du_container_ou_ID_du_container>
sudo docker rmi <nom_de_l'image_ou_ID_de_l'image>

Voilà, nous avons supprimé à la fois le container (via son identifiant de container) et l'image dirsearch.

Plus tôt dans cet article nous avons lancé l'image dirsearch via cette commande:

sudo docker run "dirsearch:0.3.8"

Ce qui nous a affiché ceci:

En fait il est possible de lancer un container en lui spécifiant une commande à exécuter. Pour illustrer cet exemple je vous invite à récupérer l'image ubuntu:latest depuis le hub docker en utilisant cette commande:

sudo docker pull ubuntu:latest

Cette image contient tout ce qui est nécessaire pour lancer la dernière version du système d'exploitation ubuntu. Lorsque l'on lance un container il sera possible de demander à ce que ce dernier exécute une commande. On utilisera la commande suivante pour indiquer à notre container qu'il devra exécuter la commande id:

sudo docker run ubuntu:latest id 

Ce qu'il est important de savoir ici c'est que par défaut lorsque vous lancez un container, docker va exécuter la commande:

/bin/sh -c

Suivie de l'ensemble des arguments que vous avez passé à la commande run. La commande finale exécutée ici est donc:

/bin/sh -c id

Pour plusieurs raisons (principalement de l'administration système) il sera nécessaire d'obtenir un shell root au sein de notre container de manière à en modifier les fichiers de configuration par exemple. Ça sera possible en utilisant cette commande:

sudo docker run -it ubuntu:latest

Les options -i et -t nous permettent respectivement d'obtenir un shell interactif ainsi qu'un TTY. Ce comportement par défaut est indiqué par la directive CMD présente dans le Dockerfile. Cette directive indique quelle est la commande par défaut à exécuter lorsque un container est créé. Dans le cas de l'image ubuntu:latest c'est effectivement la commande bash qui est lancé ce qui explique pourquoi nous obtenons un shell root.

En reprenant l'exemple du Dockerfile du projet Dirsearch on remarque que ce n'est pas un shell qui est exécuté par défaut mais une option "--help":

CMD ["--help"]

Mais ce n'est pas tout, une autre instruction peut retenir notre attention: ENTRYPOINT. Cette instruction indique à notre container quel binaire ou script il doit exécuter une fois lancé:

ENTRYPOINT ["/root/dirsearch.py"]

Ici le container, une fois lancé, exécutera le script dirsearch.py situé dans le répertoire /root. Si aucun paramètre ça sera l'argument "--help" qui sera exécuté ce qui explique pourquoi nous avons obtenu le man du tool en exécutant:

En écrivant ces instructions, greenmind-sec (le contributeur qui a ajouté le Dockerfile au projet via merge-request) à configurer le container pour qu'il s'exécute comme un exécutable/script grâce aux deux instructions CMD et ENTRYPOINT que nous verrons plus en détails dans le prochain article.