Astuces sur l'écriture de commandes shell dans les RUN de Dockerfile
Les fichiers Dockerfile
de Docker permettent la
création d’images Docker, qui deviendront par la suite des conteneurs.
Dans ces fichiers il est possible d’indiquer des commandes CLI à exécuter lors
de la phase de construction (build) de l’image via l’instruction RUN
.
Je vais partager quelques petites astuces concernant l’écriture de commandes
pour RUN
.
Cela ne les rendra pas plus performantes, mais plus lisibles, y compris dans les historiques git.
L’instruction RUN
s’utilise de 2 façons :
La forme shell, qui utilise l’interpréteur de commande
/bin/sh -c
oucmd /S /C
selon la plateforme (ou ce que l’éventuelle instructionSHELL
aura configuré) :1
RUN <command>
La forme exec, qui n’utilise pas de shell mais directement l’exécutable :
1
RUN ["executable", "param1", "param2"]
L’écriture de longues commandes sous la forme shell peut être un peu difficile à lire, suivre et/ou maintenir.
|
|
Surtout qu’il est conseillé, pour limiter la taille des images Docker,
d’exécuter plusieurs commandes au sein de la même instruction RUN
et de faire
du ménage dans les dossiers de cache APT du système, ce qui donne quelque chose
comme ça :
|
|
Je propose d’écrire cette longue commande d’une autre façon.
On peut déjà aérer les commandes de l’instruction en la répartissant sur
plusieurs lignes via des \
et des sauts de ligne, comme suit :
|
|
On peut aussi aérer à l’intérieur de chaque commande :
|
|
C’est déjà plus lisible et plus facile à maintenir au fil du temps.
Mais, par exemple, ajouter un module à la commande a2enmod
peut, dans
certains cas demander de modifier 2 lignes.
Ici j’ai ajouté le module userdir
, et comme je les organise par ordre
alphabétique j’ai dû également modifier la ligne de suexec
pour retirer le
&&
causant un diff assez verbeux :
|
|
Le même problème se poserait si je voulais :
- rajouter une commande au tout début (avant
apt-get update
) - rajouter un paramètre ou une commande à la toute fin
C’est, d’après moi quelque chose de dérangeant à voir dans l’historique du code d’un projet (e.g. git) : le nombre de lignes modifiée est plus élevé que ce qui est réellement changé, les revues de codes sont impactées et les recherches via git pickaxe sont encombrées de lignes non pertinentes.
Afin de palier ces soucis, j’utilise la forme suivante :
|
|
Explications :
Ajouter un
\
+ saut de ligne dès le début de l’instructionRUN
me permet de pouvoir rajouter un commandecommande_0
à exécuter en premier sans toucher à la ligneRUN
ni à celle decommande_1
.Chaque commande est suivie de
&&
(car ici on veut enchaîner toutes les commandes en cas de succès : à adapter selon vos besoins) puis d’un\
+ saut de ligne.Ainsi ajouter une commande entre 2 commandes ou après la dernière (ici
commande_4
) peut se faire sans toucher aucune autre ligne.La même logique s’applique aux options et paramètres d’une même commande sans le
&&
bien entendu). Je conseille d’utiliser cette forme multi-ligne pour toute commande pouvant avoir un nombre variable d’options et/ou paramètres de se laisser la possibilité d’en ajouter sans toucher aux autres lignes de la même commande.Le
true
en dernière ligne est là pour aller avec le&&
de la ligne précédente.
Au final, cela donne ceci :
|
|
Notez qu’il est aussi possible d’utiliser des chaînes de texte heredocs dans
la forme shell avec BuildKit comme
l’annonçait cet article de Docker
et la documentation
depuis que cette fonctionnalité a été ajoutée dans la version stable de la
syntaxe syntax=docker/dockerfile:1
(et sans syntaxe spéciale dès Docker
v23.0).
Cela permet d’écrire les commandes de RUN
sans \
ni &&
:
|
|
Si vous aimez le contenu, vous pouvez aider
Sponsor