Astuces pour écrire des scripts shell et des définitions de conteneurs (Dockerfile, Containerfile)
Je me retrouve régulièrement à faire des petits scripts shell, même si je ne suis pas un expert de cet outil.
Même en 2024, les développeurs sont régulièrement encore confrontés aux scripts shells, parfois sans qu’ils le sachent.
Par exemple, quand on crée des fichiers de définition de conteneurs (Containerfile
aussi connu sous le nom originel de Dockerfile), chaque
commande définie dans une ligne RUN
est
exécutée par défaut dans un shell (shell form).
Pour écrire ces fichiers, une bonne pratique est d’éviter d’écrire
plusieurs commandes RUN
d’affilée dans un
Containerfile pour éviter de faire créer trop d’images
Docker intermédiaires inutiles pendant la création du conteneur
(on évite ainsi de créer trop de snapshots du système de
fichiers).
J’ai appris cette bonne pratique a mes débuts avec Docker et je l’ai appliquée, mais je n’ai jamais vraiment réalisé que ce n’était pas juste une ligne de shell que j’écrivais, mais plutôt un script.
Par exemple, quand on construit une image Docker avec une distribution Debian, si on a besoin d’installer un logiciel, il faudrait exécuter trois commandes:
RUN apt update
RUN apt install python3
RUN apt-get clean
La bonne pratique serait de rassembler toutes ces commandes dans une seule ligne RUN:
RUN apt update \
&& apt install python3 \
&& apt-get clean
Depuis la version 20.10.13 de Docker, on peut même utiliser la syntaxe heredoc:
RUN <<EOF
apt update
apt install python3
apt-get clean
EOF
Avec cette nouvelle syntaxe, on se rend compte que, finalement, cette suite de commandes est en réalité un vrai script shell. Il faut donc penser à appliquer les bonnes pratiques pour la création de script shell.
Quand je crée un script shell, je commence toujours par activer les
options set -euxo pipefail
pour que le script échoue à la
moindre erreur.
Récemment, sur LinuxFr.org, Marotte nous a expliqué que ces options s’appellent le bash strict mode et qu’on pourrait l’appeler le script mode, ce que je trouve en effet beaucoup plus parlant.
L’article que Marotte a partagé à propos de ce strict mode est
très détaillé et explique d’ailleurs qu’il vaut mieux aussi remplacer la
variable IFS
par IFS=$'\n\t'
, ce que je ne
connaissais pas.
Enfin, lors de la création d’un script shell, j’utilise également beaucoup l’outil shellcheck, parce qu’il permet de repérer à l’avance tous les pièges courants lors de la création de code shell.
L’exemple de la commande RUN plus haut donnerait donc:
RUN <<EOF
#!/usr/bin/env bash
set -euxo pipefail
IFS=$'\n\t'
apt update
apt install python3
apt-get clean
EOF
Au fait, un autre exemple important où je crée régulièrement des scripts shells, est lorsque je crée des tâches pour l’intégration continue et le déploiement continue de Gitlab.
De la même manière que pour les Containerfile, je ne m’étais pas rendu compte que ce sont des scripts shell, puisque les jobs d’exemples sont assez simples et sont juste une suite de ligne de commandes.
Mais dès qu’une tâche devient un peu plus complexe, il vaudrait mieux passer en script mode et utiliser la syntaxe YAML qui permet aussi de créer des blocs de strings sur plusieurs lignes.
Si on reprend les mêmes commandes que plus haut, dans un bloque script de Gitlab, ça donnerait:
exemple-mise-a-jour:
script: |
#!/usr/bin/env bash
set -euxo pipefail
IFS=$'\n\t'
apt update
apt install python3
apt-get clean
Commentaires
Répondez à ce message du Fediverse pour ajouter un commentaire sur cet article.