Alpine ou comment faire une image Docker très légère

Publié le 01/02/2016

Puisque ces temps-ci je met à profit mes compétences CoreOS/Docker de manière plus soutenue, je me suis dit que quelques articles sur mon blog pour partager quelques astuces pourrait être de bon allois (t’as vu !). Alors aujourd’hui, je vais parler de Alpine, une distribution pour conteneur très légère et pourtant très fournie.

L’un des soucis majeurs avec Docker c’est bien l’espace nécessaire pour une image. Certes, le fait de partir d’une même image de base (debian, fedora, centos…) ne va pas dupliquer l’espace (parce que Docker utilise un système d’union fs) mais tout de même… Quand on se retrouve à vouloir fournir une image qui contient un seul binaire de 1 ou 2 Mo, on a une image de 100Mo voir 200Mo à fournir. Et j’exagère à peine.

L’idée est donc de réduire un maximum l’espace nécessaire. Il y a, en premier lieu, des astuces simples à connaitre:

  • tenter de faire un maximum de chose en une seule commande “RUN”
  • supprimer les fichiers inutiles (cache apt, yum…) très rapidement et surtout dans la commande qui génère ces fichiers; par exemple, supprimer le cache et faire un “autoremove” juste après un “apt-get install” ou un “dnf install”

Mais quoiqu’il arrive, une distribution “commune” telle que debian, fedora, centos, etc. ont la facheuse tendance à installer, de base, pas mal d’outils inutiles dans une image Docker. Ce n’est pas de leur faute, loin de là, elle ne sont juste pas optimisée pour ça. Ces fichiers sont présents parce que ces distributions sont faite pour “booter” sur une machine (virtuelle ou physique).

Busybox - la base

Il existe deux distributions (si on peut les appeler comme ça) faites pour de l’embarqué et les images Docker. La première est très légère: busybox. Cette distribution embarque réellement le strict minimum et, à moins que vous ne vouliez embarquer que des binaire statiquement compilés ou ne l’utiliser que pour faire un conteneur “data only”, elle ne vous sera pas très utile. Personnellement je m’en sers pour des outils développés en Go qui n’ont pas besoin d’enregistrement libc particulier, donc sitôt que je fais un binaire qui utilise du réseau, je me retrouve avec un binaire qui ne veut pas s’exécuter sur busybox.

Heureusement pour moi, une autre distribution embarquée existe, basée sur busybox.

Alpine - la solution

Alpine est une distribution qui n’occupe que quelques megaoctets (4 Mo). La différence entre busybox et celle-ci est que Alpine propose un gestionnaire de paquet qui, en plus, propose pas mal d’outils paquagés, allant de Mysql et Mongo à Nginx en passant par Java, Go et Python.

L’outil se nomme “apk” et il est assez simple à utiliser. Tentons l’expérience.

$ docker run --rm -it alpine sh

/ # python
sh: python: not found

/ # apk add --update python
... 
OK: 51 MiB in 21 packages

/ # python
Python 2.7.11 (default, Jan 23 2016, 12:34:14) 
[GCC 5.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.

L’option “–update” permet de ne pas passer par deux commandes “alpine update; alpine add python”.

Donc, dans un Dockerfile, on aura le loisir d’installer des outils et de les supprimer si nécessaire.

Par exemple, si je veux compiler un binaire de mon projet Go, je n’ai qu’à faire:

  • deposer mes sources dans l’image
  • installer go
  • compiler mes sources
  • déplaccer le ou les binaires dans /usr/bin/
  • supprimer go (puisque j’ai compilé mes binaires)

Voilà un exemple:

FROM alpine:latest
MAINTAINER Patrice FERLET <metal3d@gmail.com>

ADD src/ /opt/src

RUN set -xe;                \
    apk add --update go     \
    cd /opt/src;            \
    go build;               \
    mv macommande /usr/bin; \
    cd /; rm -rf /opt/src;  \
    apk del --purge go;     \
    rm -rf /var/cache/apk/* 

CMD macommande

Pour résumer, après compilation, je supprime mes sources (inutile en fait puisque le layer précédent utilis ADD et que les sources sont donc préservées) puis je supprime “go” (en purgant si nécessaire) et je vire le cache “apk” qui n’a plus d’utilité.

Et le tout se fait en une commande RUN afin de ne pas avoir un layer chargé de fichiers qui seraient préservés. Donc, le principe est finalement le même qu’avec n’importe quel autre gestionnaire de paquet.

Par contre, la taille de mon image passe de 120Mo avec une Debian, à 10Mo avec Alpine.

Bilan

Voilà pour ce premier petit article parlant de Alpine. Le prochain va vous présenter CoreOS et quelques méthodes de balancing automatique. Pour l’heure, pensez à Alpine si vous voulez créer des images Docker rapidement, allégée, et ce pour des service NodeJS, Go, Java, PHP, Ruby… car le dépot apk est bien fourni

comments powered by Disqus