/ Docker

Des containeurs minimalistes avec Alpine Linux

Puisque ces temps-ci je m’amuse pas mal avec mon matériel perso’ à la maison, je met à profit mes compétences Docker de manière plus soutenue, je me suis dit que quelques articles sur mon blog pour partager quelques tricks. Alors aujourd’hui, je vais encore 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.

Heureusement pour moi, une autre distribution embarquée existe, basée sur busybox. Nous en avons déjà parlé dans l’article sur LEMP.

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.

*gabriel@Ubuntu-server3:~$ sudo docker run --rm -it alpine sh
[sudo] Mot de passe de gabriel :

/ # golang sh: golang: not found /

/ # apk add --update go fetch http://dl-cdn.alpinelinux.org/alpine/v3.6/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.6/community/x86_64/APKINDEX.tar.gz

(1/13) Installing binutils-libs (2.28-r2)
(2/13) Installing binutils (2.28-r2)
(3/13) Installing gmp (6.1.2-r0)
(4/13) Installing isl (0.17.1-r0)
(5/13) Installing libgomp (6.3.0-r4)
(6/13) Installing libatomic (6.3.0-r4)
(7/13) Installing pkgconf (1.3.7-r0)
(8/13) Installing libgcc (6.3.0-r4)
(9/13) Installing mpfr3 (3.1.5-r0)
(10/13) Installing mpc1 (1.0.3-r0)
(11/13) Installing libstdc++ (6.3.0-r4)
(12/13) Installing gcc (6.3.0-r4)
(13/13) Installing go (1.8.3-r0)
Executing busybox-1.26.2-r5.trigger OK: 266 MiB in 24 packages
/ # go Go is a tool for managing Go source code. Usage: go command [arguments] The commands are: build compile packages and dependencies clean remove object files doc show documentation for package or symbol env print Go environment information bug start a bug report fix run go tool fix on packages fmt run gofmt on package sources generate generate Go files by processing source get download and install packages and dependencies install compile and install packages and dependencies list list packages run compile and run Go program test test packages tool run specified go tool version print Go version vet run go tool vet on packages Use "go help [command]" for more information about a command. Additional help topics: c calling between Go and C buildmode description of build modes filetype file types gopath GOPATH environment variable environment environment variables importpath import path syntax packages description of package lists testflag description of testing flags testfunc description of testing functions Use "go help [topic]" for more information about that topic.
/ # Executing busybox-1.26.2-r5.trigger sh: Executing: not found
/ # OK: 266 MiB in 24 packages sh: OK:: not found / #

L’option “–update” permet de ne pas passer par deux commandes “alpine update; alpine add go”.
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:

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

Voilà un exemple:

FROM alpine:latest
MAINTAINER Gabriel SAGNARD gabrielsagnard26@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 utilise ADD et que les sources sont donc préservées) puis je supprime “go” (en purgeant 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 cet autre petit article parlant de Alpine. 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