Utilisation de Docker

Après la présentation des images docker et de leur fabrication dans le billet précédent sur les Conteneurs et Docker, il est temps de voir comment utiliser les conteneurs en dehors de l’Intégration continue à Systerel.

Nous passerons rapidement sur l’installation et la configuration de docker avant de passer en revue les principales commandes.

Note sur Podman

Afin de simplifier son utilisation, Podman a repris la quasi totalité des commandes de Docker pour son propre client CLI. Il est donc possible de suivre cet article pour utiliser Podman en remplaçant simplement docker par podman au début des commandes. Pour ce qui est de son installation, les instructions officielles sont disponibles ici.

Installation et configuration de Docker

Linux

Pour Linux, référez-vous au wiki du SI qui donne les indications nécessaires à l’installation.

Notez bien que chaque commande docker doit être préfixée par sudo1 sauf si votre utilisateur a été ajouté au groupe docker.

Windows

Certaines personnes à Systerel ont réussi à utiliser docker avec WSL2 en utilisant ces deux tutoriels :

PS C:\Windows\system32> wsl -l -v
  NAME      STATE           VERSION
Ubuntu    Running         1
PS C:\Windows\system32> wsl --set-version Ubuntu 2
La conversion est en cours. Cette opération peut prendre quelques minutes...
Pour plus dinformations sur les différences de clés avec WSL 2, visitez https://aka.ms/wsl2
La conversion est terminée.

Utilisation d’une image docker

docker run

La commande principale pour exécuter une image docker est docker run. Par exemple, pour lancer l’image docker qui affiche Hello from Docker! :

$ docker run hello-world

Les options couramment utilisées sont :

  • --rm pour détruire le conteneur une fois qu’il a été exécuté [doc],
  • -it pour garder STDIN ouvert et allouer un pseudo-terminal et permettre une session interactive [doc],
  • -v pour monter un volume local dans le conteneur (par exemple, -v $(pwd):/data) [doc],
  • -p pour la redirection de port du conteneur vers la machine hôte (par exemple, -p 8000:80) [doc].

docker exec / docker ps

Si l’image exécute un binaire qui ne se termine pas, il est possible de lancer une commande dans ce conteneur avec docker exec. C’est très utile pour aller inspecter l’état du conteneur lors de la mise au point d’un Dockerfile.

Par exemple si on a lancé un conteneur alpine avec un shell qui attend une commande :

$ docker run --rm -it --name=calpine alpine sh

On peut voir que le conteneur est en train d’être exécuté avec la commande docker ps (et tous les conteneurs, même ceux stoppés avec la commande docker ps -a).

$docker ps   
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
ec551687cc1f   alpine    "sh"      9 minutes ago   Up 9 minutes             calpine

On peut lancer dans un autre terminal :

$ docker exec calpine ls |  head 
bin
dev
etc
home
lib
media
mnt
opt
proc
root

Montage de répertoire

Il est souvent utile de permettre au conteneur d’avoir accès à un répertoire de la machine hôte. Cela se fait avec l’option -v ou --volume de docker-run dont la syntaxe est la suivante :

docker run --volume[=[[HOST-DIR:]CONTAINER-DIR[:OPTIONS]]]]

Par exemple, la commande suivante va afficher le contenu de votre répertoire de travail :

docker run -it --rm --volume "$PWD":/data bash ls /data

Attention 1/2

Le montage peut poser problème aux programmes du conteneur si :

  1. ils attendent la présence d’une arborescence donnée (/home/user par exemple),
  2. un des sous-répertoires est un lien vers une autre partie du système de fichier,
  3. les fichiers du répertoire courant contiennent des liens symboliques qui pointent en dehors du montage.

Pour résoudre le problème 1, il faut monter dans le répertoire attendu par les outils. Pour les problèmes 2 et 3 il faut veiller à monter une arborescence contenant les fichiers origines et non pas les liens symboliques.

On peut par exemple faire :

mount_point=$(realpath "$PWD")
docker run -it --rm --volume "$mount_point:$mount_point"

Attention 2/2 — UID

L’UID (User ID) dans le docker est en général différent de l’UID sur la machine hôte. Cela peut poser des problèmes d’accès aux fichiers (par défaut la commande est lancée en tant que root dans le conteneur).

C’est notamment génant pour un docker qui est utilisé comme environnement de développement par plusieurs utilisateurs différents (si il n’est utilisée qu’en CI, ce n’est en général pas génant).

Il est possible d’utiliser l’option --user qui accepte la syntaxe suivante :

docker run --user [user | user:group | uid | uid:gid | user:gid | uid:group ] …

La commande suivante permet de lancer la commande avec le même uid que celui de l’utilisateur qui lance la commande, même si elle est lancée via sudo (l’ajout du gid est laissé comme exercice au lecteur).

sudo docker run --user "$(id -u "$(logname)")"  -it --rm bash id …

Note — login vs UID

Si vous utilisez votre nom de login, vous aurez vraisemblablement l’erreur suivante : docker: Error response from daemon: unable to find user <user>: no matching entries in passwd file, car il est peu probable que votre identifiant apparaisse dans le fichier /etc/passwd du conteneur.

Utiliser votre UID numérique résoudra le problème.

Montage d’un répertoire temporaire

Si l’application du docker écrit des fichiers qui n’ont pas vocation à persister d’un lancement à l’autre, il est recommandé d’utiliser un volume temporaire au moyen de l’option --tmpfs [doc]. Par exemple :

docker run -it --tmpfs /app nginx:latest

Redirection de port

Le conteneur a parfois pour rôle d’héberger l’exécution d’un démon qui fournit un service sur un des ports de l’interface réseau. Il est possible de publier le port d’un conteneur, soit sur le même numéro de port, soit sur un autre numéro à l’aide des options -p ou --publish. La syntaxe est :

--publish ip:[hostPort]:containerPort | [hostPort:]containerPort

Lancez par exemple le serveur web nginx qui écoute par défaut sur le port 80 pour qu’il écoute sur le port 8000 sur votre machine hôte :

$ docker run --rm -p 8000:80 nginx 

Sur votre navigateur web, vous pouvez naviguer sur l’adresse http://localhost:8000 pour voir la page d’accueil par défaut de nginx :

Page d’accueil de Nginx

Affichage des logs

La commande docker logs permet d’afficher les logs d’un conteneur. On l’utilise souvent avec l’option -f pour avoir un affichage en continu.

Maintenance des images

Il faut parfois faire un peu de ménage pour supprimer les conteneurs ou images inutilisées. Les commandes suivantes sont utiles pour ce faire :

  • docker images pour lister les images disponibles dans le cache local,
  • docker rmi pour supprimer une ou plusieurs images du cache local,
  • docker system prune pour supprimer les images non référencées ou toutes les images inutilisées.
  • docker volume ls pour lister les volumes existants,
  • docker volume prune pour supprimer les volumes non utilisés,
  • docker save/docker load pour sauvegarder et importer une image dans ou depuis une archive tar. Parfois utile pour copier une image sur une machine qui n’a pas accès à un dépôt d’image.

Autres commandes couramment utilisées

  • docker cp pour copier des fichiers entre le conteneur et le système de fichier local,
  • docker stats pour avoir un aperçu en temps réel de la consommation des ressources par les différents conteneurs s’exécutant sur la machine.

  1. Il est aussi possible d’utiliser sudo -g docker pour éviter de passer root

Commentaires