A force d’utiliser Docker, si l’on ne prête pas attention à la gestion des conteneurs et des images, on sature rapidement l’espace disque.

Les conteneurs

Suppression automatique des conteneurs

Pour rappel, un conteneur peut être automatiquement supprimé quand il s’arrête en précisant l’option –rm :

$ docker run busybox date
Tue Jan  5 22:25:17 UTC 2016

$ docker ps -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                      PORTS                    NAMES
f3a949beb7ae        busybox                "date"                   4 seconds ago       Exited (0) 3 seconds ago                             fervent_thompson

$ docker run busybox date
Tue Jan  5 22:26:00 UTC 2016

$ docker ps -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                      PORTS                    NAMES
f6f518e44d22        busybox                "date"                   2 seconds ago       Exited (0) 2 seconds ago                             loving_kowalevski
f3a949beb7ae        busybox                "date"                   12 seconds ago      Exited (0) 11 seconds ago                            fervent_thompson

$ docker run --rm busybox date
Tue Jan  5 22:26:11 UTC 2016

$ docker ps -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                      PORTS                    NAMES
f6f518e44d22        busybox                "date"                   14 seconds ago      Exited (0) 13 seconds ago                            loving_kowalevski
f3a949beb7ae        busybox                "date"                   24 seconds ago      Exited (0) 23 seconds ago                            fervent_thompson

Suite aux deux premiers appels, un nouveau conteneur est persisté. Lors du troisième appel avec l’option –rm, le nouveau conteneur n’est pas persisté.

Cependant, il arrive parfois d’oublier de spécifier cette option. Alors comment faire le ménage ?

Suppression manuelle des conteneurs

La commande docker rm permet de supprimer des conteneurs. En la combinant avec la commande docker ps -a, il est possible de faire rapidement le ménage. Par exemple voici la commande qui permet de supprimer tous les conteneurs arrêtés depuis plus d’une semaine :

$ docker ps -a | grep 'weeks ago' | awk '{print $1}' | xargs --no-run-if-empty docker rm

Une autre solution radicale est d’arrêter et supprimer tous les conteneurs de cette façon :

$ docker stop $(docker ps -q) && docker rm $(docker ps -qa)

Malgré le nettoyage des conteneurs inutiles, il se peut que l’espace disque soit toujours saturé. C’est souvent le cas quand on utilise ou teste beaucoup d’images différentes.

Les images

Suppression des images inutiles

Les images peuvent être gérées de la même façon que les conteneurs. docker images liste les images. Et l’option -a permet d’afficher toutes les images intermédiaires. De même, la commande docker rmi permet de supprimer une image. Une image ne peut être supprimée que s’il n’y a pas de conteneur qui l’utilise.

Vous n’utilisez plus ZooKeeper ? Voici comment lui dire “au revoir” avec Docker :

$ docker rmi jplock/zookeeper
Untagged: jplock/zookeeper:latest
Deleted: f0a59693878e1014467e796dc641e0550f7ebdf3d2a06072fed753ee22791ad7
Deleted: df0365f272952a1e98e7206abbe49bc2f3a4075870b7ff13710ecc3887fdefc5
Deleted: a7bd737e44fd7b74e4a5e2fbc845a15ec96a0102058749021dee7df47c4237f3
Deleted: 2f276e169ce87c426a97e4eb9bf16d281c868821a4804ec40777f303f15b73e1
Deleted: 0b3118887bdc1526e83bf423d3f907bc7769474e0fa826cb7dd1487488f7b049
Deleted: 3317d80d5da6209d8a7ac8bb707bcac3d7b4a3d0a913ccb6f2c8ca4641fb8640
Deleted: 2124b0af39c37fd9b116ddd67ca67e5df061bf8b8bbb64f307b95150b218fed8
Deleted: c0d9f3547756cebb67644ccc7b7d3e1dabf13b55db88274c41195812e967c90e
Deleted: 2419aec0e767b258b4dc994d045989dfc463421af57fa8d21efab1e863f54b9f
Deleted: ac42b87cce0c4df68ba51e3cd82057845fa97b2f15f5a72d0999c12f8dbee1f7
Deleted: 75f2d40e68ea4ed8593ed682d20b53abe99436be64cac507439f55d73905f770
Deleted: d634beec75db64004deb5878e6234311d42edc0a4a19199b300ae4c4c9e2e989

Suppression des images non-référencées

Parmis les images intermédiaires, il y a des images qui ne sont utilisées par personne. Elles apparaissent souvent avec la commande docker build mais aussi avec docker pull. En attendant un système de garbage collection, il est possible supprimer ces images avec la commande suivante :

$ docker rmi $(docker images -f "dangling=true" -q)
Deleted: 0618a75d6877aed2245a1db9abb658b6512c681733225684a4275d79870f50c2
Deleted: 6508ed60259350211bce0c81e20a7bd8d06a39a946bc914253d1b77e52187c5f
Deleted: 2a7fa229f7a74b7e0b19d1415371605ea251c75fa062d07a9b2df52e9345f218
Deleted: d827652146f6dfa91cc7069321b793039d31d15a5ffaa21ff002780f8742a590
Deleted: 07c0148e366f93d28323fc5dca074a28988b6e340a44fc565aa3f052899e91d3

Avec toutes ces commandes, vous devriez avoir récupéré pas mal d’espace disque. Devriez ? Oui, si vous utilisez Docker directement sous GNU/Linux ! En revanche, si vous passez par VirtualBox via Docker Machine ou Vagrant, c’est une autre histoire…

Les VM

Compression de la VM VirtualBox

En effet, malgré le nettoyage dans les conteneurs et les images, l’image de la VM VirtualBox n’a pas réduit de taille. Pourtant l’espace semble libéré quand on se connecte dans la VM et exécute la commande ci-dessous :

$ df
Filesystem                Size      Used Available Use% Mounted on
tmpfs                   896.5M    115.2M    781.3M  13% /
tmpfs                   498.1M         0    498.1M   0% /dev/shm
/dev/sda1                18.2G      7.0G     10.3G  40% /mnt/sda1
cgroup                  498.1M         0    498.1M   0% /sys/fs/cgroup
none                     75.0G     72.7G      2.3G  97% /c/Users
/dev/sda1                18.2G      7.0G     10.3G  40% /mnt/sda1/var/lib/docker/aufs

Le montage /mnt/sda1/var/lib/docker/aufs correspond au répertoire /var/lib/docker où sont stockées les images Docker. Ici l’espace utilisé ne fait que 7Go (au lieu de 12Go avant le ménage) ! VirtualBox ne semble pas réduire l’espace utilisé par l’image vmdk de la VM quand l’espace est libéré. Néanmoins, il est possible de compacter ce fichier.

La première étape consiste à remplir de zéro les espaces libres en exécutant dans la VM la commande suivante :

$ cat /dev/zero > zero.fill;sync;sleep 1;sync;rm -f zero.fill
cat: write error: No space left on device

Si le répertoire de stockage des images est sur une partition spécifique, il faut exécuter la commande dans le bon répertoire :

$ cd /var/lib/docker
$ sudo su
$ cat /dev/zero > zero.fill;sync;sleep 1;sync;rm -f zero.fill
cat: write error: No space left on device

Une fois les espaces libres remplis de zéro, il faut arrêter la VM puis lancer la défragmentation et la compression de l’image avec un utilitaire VMWare :

$ ls -lagh /c/Users/pnom/.docker/machine/machines/docker-test/*.vmdk
-rw-r--r-- 1 Domain Users  13G Jan  4 12:20 disk.vmdk

$ curl -o vdiskmanager-windows-7.0.1.exe.zip 'http://kb.vmware.com/selfservice/viewAttachment.do?attachID=1023856-vdiskmanager-windows-7.0.1.exe.zip&documentID=1023856'
$ unzip vdiskmanager-windows-7.0.1.exe.zip
$ vdiskmanager-windows-7.0.1.exe -d /c/Users/pnom/.docker/machine/machines/docker-test/disk.vmdk
  Defragment: 100% done.
Defragmentation completed successfully.
$ vdiskmanager-windows-7.0.1.exe -k /c/Users/pnom/.docker/machine/machines/docker-test/disk.vmdk
  Shrink: 100% done.
Shrink completed successfully.

$ ls -lagh /c/Users/pnom/.docker/machine/machines/docker-test/*.vmdk
-rw-r--r-- 1 Domain Users 7.9G Jan  5 23:15 disk.vmdk

Destruction de la docker-machine

Une autre alternative très efficace mais bien plus radicale est de recréer une nouvelle docker-machine comme ceci :

$ docker-machine stop default && docker-machine rm default && docker-machine create -d virtualbox docker-test

Cette solution oblige à télécharger de nouveau toutes les images, reconstruire tous les images personnalisées et relancer tous les conteneurs. Une étape assez longue que l’on ne souhaite pas toujours refaire…

Le mot de la fin

Dans cet article, il a été mis en évidence que Docker manque peut-être d’un système de garbage collection. Des développeurs indépendants comme Spotify ou N. De Loof ont implémenté leur propre garbage collector. Des solutions peut-être à tester…

Dans un même temps, la gestion de la taille du fichier image VirtualBox utilisé par Docker Machine n’est pas optimal. Ne faudrait-il pas prévoir un système de compression automatique ?

Enfin, il serait peut-être intéressant de permettre de créer une Docker Machine qui utilise un disque externe pour la partition de stockage des images Docker. Ce disque pourrait alors être partagé entre différente Docker Machine. Ce qui permettrait d’économiser de l’espace disque.

A vos balayettes !