đ Conteneuriser (manuellement) un logiciel en image de conteneur
1. Motivation
Nous avons vu tout au long du cours qu’il Ă©tait possible d’utiliser une image de conteneur dĂ©jĂ disponible "sur Ă©tagĂšre" afin de facilement crĂ©er un nouveau conteneur. Une premiĂšre catĂ©gorie d’images de conteneur sont celles qui fournissent chacune un environnement minimal sur la base d’un systĂšme d’exploitation (Ubuntu, Alpine, etc.) ou dĂ©diĂ©e Ă une technologie (Python, Julia, Java, etc.). Une seconde catĂ©gorie d’images sont celles qui permettent chacune de dĂ©ployer facilement un logiciel spĂ©cifique (et l’environnement minimal associĂ©), qui aura Ă©tĂ© prĂ©-installĂ© et prĂ©-configurĂ© au sein de la dite image.
Dans ce cours, il nous reste Ă comprendre comment faire pour crĂ©er une nouvelle image de conteneur, et particuliĂšrement une image de conteneur de la seconde catĂ©gorie (Ă savoir une image qui fournit un logiciel spĂ©cifique). En effet, prĂ©parer une image de conteneur immutable et complĂšte est une maniĂšre trĂšs robuste et efficace de permettre le dĂ©ploiement d’un logiciel fraichement dĂ©veloppĂ©.
| On utilise parfois l’expression "conteneuriser un logiciel" pour parler de la crĂ©ation d’une image de conteneur pour un logiciel. |
2. Principe
Pour rappel, une image de conteneur est quasiment de mĂȘme nature qu’un conteneur : elle dĂ©finit un mini-environnement et tout ce dont il est composĂ© (fichiers, rĂ©pertoires, etc.). La principale diffĂ©rence est qu’une image de conteneur est immutable â c’est Ă dire qu’elle est figĂ©e dans un Ă©tat non modifiable â tandis qu’un conteneur est mutable â c’est Ă dire que son Ă©tat peut ĂȘtre modifiĂ©. Une consĂ©quence de cette dĂ©finition est qu’il n’est pas possible d’exĂ©cuter un processus au sein d’une image de conteneur, puisqu’un processus nĂ©cessite un environnement mutable â c’est pour cette raison qu’il faut toujours crĂ©er un nouveau conteneur Ă partir d’une image pour dĂ©marrer un processus.
Ainsi, puisqu’une image de conteneur n’est rien d’autre qu’un conteneur immutable, la crĂ©ation d’une nouvelle image de conteneur peut s’accomplir en crĂ©ant un nouveau conteneur temporaire Ă partir d’une image de conteneur existante dite "de base", puis en modifiant ce conteneur temporaire, et enfin en rendant ce conteneur temporaire immutable.
La crĂ©ation d’une nouvelle image de conteneur Ă partir d’une image de base peut se rĂ©sumer ainsi :
-
(si nĂ©cessaire) L’image de base pressentie est tĂ©lĂ©chargĂ©e auprĂšs d’un registre distant, et est stockĂ©e dans le stockage local d’images de l’environnement utilisĂ© pour construire notre image.
-
Un conteneur temporaire est instanciĂ© Ă partir de l’image de base.
-
Ce conteneur temporaire est modifiĂ© afin d’y ajouter notamment :
-
le logiciel que l’on souhaitera dĂ©ployer,
-
toutes les dépendances du logiciel à déployer (bibliothÚques, exécuteurs, utilitaires, etc.).
-
si pertinent, les fichiers/rĂ©pertoires nĂ©cessaires Ă l’exĂ©cution de base du logiciel â par exemple des fichiers de configuration,
-
-
Le conteneur temporaire (dĂ©sormais modifiĂ©) est enregistrĂ© en nouvelle image de conteneur au sein du stockage local d’images. Lors de cet enregistrement, on vient greffer Ă cette image un ensemble de mĂ©tadonnĂ©es nĂ©cessaires au fonctionnement de l’image, en particulier :
-
Le point d’entrĂ©e, qui prend la forme d’une commande qui sera exĂ©cutĂ©e lors du dĂ©marrage d’un conteneur créé Ă partir de l’image,
-
Si besoin, le rĂ©pertoire de dĂ©part Ă partir duquel sera exĂ©cutĂ© la commande du point d’entrĂ©e de l’image,
-
Si besoin, des valeurs constantes affectĂ©es Ă certaines variables d’environnement utilisĂ©es par le logiciel.
-
-
Enfin, si souhaitĂ©, l’image de conteneur créée est tĂ©lĂ©versĂ©e vers un registre de conteneurs distant, afin de rendre l’image disponible aux utilisateurâ ices souhaitĂ©s.
3. Bien concevoir une image de conteneur
3.1. Problématique
Une fois une image de conteneur prĂ©parĂ©e pour un logiciel donnĂ©, elle sera mise entre les mains des administrateurâ ices systĂšme qui seront chargĂ©â es de dĂ©ployer le dit logiciel. Lors de cette "phase d’usage" de l’image, ces personnes devront correctement la configurer et l’exĂ©cuterâŠÂ sans se tromper !
| Lors des TPs vous avez souvent été dans cette situation, à savoir devoir utiliser une image de conteneur "sur étagÚre" en devant lire soigneusement sa documentation. |
Pour que cette phase d’usage se dĂ©roule sans accroc, il est prĂ©fĂ©rable avant de crĂ©er une image de bien concevoir et documenter l’image de conteneur en prĂ©vision de son usage final. En effet, lorsqu’un conteneur sera créé Ă partir de l’image, il faudra s’assurer que le processus logiciel exĂ©cutĂ© reçoive toutes les donnĂ©es, valeurs de configuration, et accĂšs au rĂ©seau dont il pourrait avoir besoin. L’image de conteneur doit anticiper cela au travers de son Ă©tat initial et de sa documentation.
Dans toutes les Ă©tapes qui suivent, un point rĂ©current sera de bien distinguer ce qui doit prĂ©-exister (autrement dit des "constantes") dans l’image de conteneur â valeurs de configuration par dĂ©faut, fichiers, etc. â et ce qui sera apportĂ© (autrement dit des "variables") uniquement lors de la crĂ©ation d’un conteneur Ă partir de l’image â valeurs de configurations, fichiers, montages, accĂšs rĂ©seau, etc.
| Si on fait un parallĂšle avec la programmation, on peut voir une image de conteneur comme une sorte de fonction prĂȘte Ă l’emploi, que l’on peut ensuite appeler lorsque c’est nĂ©cessaire. Or une fonction doit ĂȘtre clairement conçue en terme de donnĂ©es entrĂ©es (paramĂštres) et donnĂ©es de sorties (valeurs de retour), et doit ĂȘtre bien documentĂ©e pour expliquer comment chaque entrĂ©e peut affecter les sorties possibles. |
3.2. Ătape 1 : dĂ©finir le mode de configuration de l’image
Tout au long du cours, nous avons vu qu’une prĂ©occupation est de bien configurer un logiciel que l’on dĂ©ploie. Ainsi, si on souhaite rendre un logiciel dĂ©ployable via une image de conteneur, il est utile de se poser les questions suivantes :
-
avant tout, est-ce que le logiciel que l’on souhaite conteneuriser est configurable ?
-
via des arguments en ligne de commande ?
-
via un fichier de configuration ?
-
via des variables d’environnement ?
-
-
souhaite-t-on prĂ©-configurer le logiciel au sein de l’image, avec certaines constantes ?
-
souhaite-t-on que l’utilisateur de l’image puisse configurer le logiciel (partiellement ou entiĂšrement) ?
-
de quelle maniĂšre est-il pertinent de permettre la configuration du logiciel lors de l’utilisation de l’image ?
Concernant le dernier point, comme il n’est pas pratique de passer des arguments en ligne de commande Ă un logiciel conteneurisĂ©, on privilĂ©gie surtout les deux autres mĂ©thodes :
-
soit en passant un fichier de configuration par montage de fichier,
-
soit en passant des variables d’environnement au conteneur directement,
-
soit via un mélange de ces deux méthodes.
3.2.1. Méthode A : passer un fichier de configuration par montage de fichier
Si le logiciel conteneurisĂ© a Ă©tĂ© Ă l’origine conçu pour se configurer en lisant un fichier de configuration, alors il est possible de directement reposer sur ce mode de configuration. Il sera alors nĂ©cessaire pour l’utilisateurâ irce future de l’image de devoir Ă©crire un fichier de configuration, et de le fournir au logiciel conteneurisĂ© Ă l’aide d’un montage de fichier.
Il sera pertinent de documenter l’image de conteneur pour expliquer qu’un fichier de configuration est attendu Ă un emplacement prĂ©cis (c’est Ă dire, l’emplacement oĂč il sera cherchĂ© par le processus en exĂ©cution) dans le futur conteneur.
3.2.2. MĂ©thode B : dĂ©finir et/ou utiliser des variables d’environnement
Une stratĂ©gie trĂšs populaire pour configurer un logiciel conteneurisĂ© est de reposer sur des variables d’environnement. Le grand avantage de cette approche est qu’elle est repose sur un mĂ©canisme assez universel, et que les moteurs de conteneurisation permettent trĂšs facilement de dĂ©finir des variables d’environnement lors de l’exĂ©cution d’un conteneur.
Lorsqu’on prĂ©pare une image de conteneur, deux cas de figure sont possibles :
-
Dans le cas le plus simple, le logiciel conteneurisĂ© a Ă©tĂ© dĂšs le dĂ©part construit pour se configurer au travers de variables d’environnement. Il faut alors bien analyser les variables d’environnement comprises par le logiciel et en dĂ©duire :
-
celles pour lesquelles il faut fixer des valeurs constantes,
-
celles qu’il faudra laisser Ă configurer pour l’utilisateur final de l’image de conteneur.
-
-
Dans un cas plus complexe, il est possible que le logiciel que l’on conteneurise n’ait pas Ă©tĂ© au dĂ©part conçu pour se configurer via des variables d’environnement. Si on souhaite tout de mĂȘme pouvoir permettre une configuration via des variables d’environnement, on peut dĂ©finir de nouvelles variables d’environnement juste pour l’image de conteneur. Cependant, comme elles ne seront pas lues par le logiciel, il est nĂ©cessaire que l’image de conteneur possĂšde un point d’entrĂ©e qui fera usage de ces nouvelles variables d’environnement â par exemple en les transformant en arguments en ligne de commande.
Dans tous les cas, il sera pertinent de documenter l’image de conteneur pour expliquer les choix rĂ©alisĂ©s.
3.3. Ătape 2 : dĂ©finir le point d’entrĂ©e
Comme dĂ©jĂ vu dans le cours, le point d’entrĂ©e d’une image de conteneur dĂ©finit quel processus logiciel est exĂ©cutĂ© lors du dĂ©marrage d’un conteneur qui instancie cette image. C’est tout simplement une commande exĂ©cutĂ©e dans le conteneur lors du dĂ©marrage de ce dernier.
En principe, le point d’entrĂ©e est donc simplement la commande qui permet de dĂ©marrer le logiciel conteneurisĂ©. Cependant, si le logiciel Ă exĂ©cuter nĂ©cessite des arguments en ligne de commande, il est nĂ©cessaire de les lui fournir dans le point d’entrĂ©e :
-
soit sous la forme de constantes,
-
soit sous la forme de variables d’environnement dont les valeurs seront fixĂ©es lors de la future crĂ©ation du conteneur.
Et Ă nouveau, il sera pertinent de documenter l’image de conteneur pour expliquer les choix rĂ©alisĂ©s.
3.4. Ătape 3 : anticiper les points de montage nĂ©cessaires
Si le logiciel conteneurisé devra lire ou écrire des fichiers durant son exécution, alors il est utile de se poser les questions suivantes :
-
Est-ce que le logiciel utilisera des fichiers constants, qui seront toujours les mĂȘmes, d’une exĂ©cution Ă une autre ?
-
Si oui, ces fichiers peuvent ĂȘtre ajoutĂ©s Ă lors de la crĂ©ation de l’image.
-
-
Est-ce que le logiciel devra lire des fichiers fournis par l’utilisateurâ ice du logiciel ?
-
Si oui, ces fichiers devront ĂȘtre fournis Ă l’aide de montages de rĂ©pertoires/fichiers.
-
-
Est-ce que le logiciel devra produire des fichiers qui devront ĂȘtre rĂ©cupĂ©rĂ©s par l’utilisateurâ ice du logiciel ?
-
Si oui, un point de montage devra ĂȘtre créé par l’utilisateurâ ice pour pouvoir rĂ©cupĂ©rer les dits fichiers.
-
-
Est-ce que le logiciel stocke son Ă©tat sous la forme de fichiers, et est-ce qu’on souhaite faire persister cet Ă©tat d’une exĂ©cution du logiciel Ă une autre ?
-
Si oui, un point de montage devra ĂȘtre créé par l’utilisateurâ ice pour garantir la persistence des dits fichiers en cas de supression du conteneur.
-
Encore une fois, il sera pertinent de documenter l’image de conteneur pour expliquer les choix rĂ©alisĂ©s.
3.5. Ătape 4 : anticiper les accĂšs rĂ©seau nĂ©cessaires
Si le logiciel conteneurisĂ© aura besoin de communiquer avec d’autres processus logiciels, il est important de documenter Ă la fois :
-
les ports rĂ©seaux sur lesquels le logiciel conteneurisĂ© est susceptible d’Ă©couter,
-
les logiciels extĂ©rieurs auxquels le logiciel conteneurisĂ© souhaitera se connecter (par exemple un accĂšs Ă une base de donnĂ©es), et comment configurer accĂšs rĂ©seaux Ă ces logiciels (par exemple l’adresse rĂ©seau et le port auxquels se connecter).
Ă nouveau, il sera pertinent de documenter l’image de conteneur pour expliquer les choix rĂ©alisĂ©s.
3.6. Exemples
On souhaite prĂ©parer une image de conteneur pour Automatic-Image-Converter, notre logiciel capable de convertir en continu des photos d’un type de fichier Ă un autre.
Ătape 1 : dĂ©finir le mode de configuration de lâimage
Automatic-Image-Converter est un logiciel qui s’attend Ă trouver quatre arguments en ligne de commande pour s’exĂ©cuter, dans un ordre strict : le rĂ©pertoire d’entrĂ©e, puis le rĂ©pertoire de sortie, puis le format vers lequel convertir, et enfin la durĂ©e entre chaque passe de conversion.
On fait le choix que les deux rĂ©pertoires (entrĂ©e et sortie) seront des constantes au sein du conteneur, Ă savoir /inputs et /outputs, et on dĂ©cide que la configuration du format et de la durĂ©e pourra se faire lors de la phase d’usage Ă l’aide de deux variables d’environnement FORMAT DURATION.
Ătape 2 : dĂ©finir le point dâentrĂ©e
En supposant que le logiciel soit copiĂ© dans l’image de conteneur Ă l’emplacement /app.jar, la commande pour exĂ©cuter Automatic-Image-Converter prend la forme :
java -jar /app.jar <répertoire entrée> <répertoire sortie> <format cible> <durée>
Sur la base des choix faits en Ă©tape 1, on fixe les deux constantes choisies pour les deux premiers arguments, et les deux variables choisies pour les deux derniers arguments, ce qui donne le point d’entrĂ©e suivant :
java -jar /app.jar /inputs /outputs $FORMAT $DURATION
Ătape 3 : anticiper les points de montage nĂ©cessaires
Le logiciel aura besoin de lire des fichiers fournis par l’utilisateur, et de produire des fichiers en consĂ©quence, dans deux rĂ©pertoires distincts (Ă savoir les constantes /inputs et /outputs fixĂ©es dans les Ă©tapes prĂ©cĂ©dentes).
On documente donc pour notre image que :
-
un montage de rĂ©pertoire est nĂ©cessaire Ă l’emplacement
/inputspour pouvoir fournir des images Ă notre logiciel, -
un montage de rĂ©pertoire est nĂ©cessaire Ă l’emplacement
/outputspour pouvoir récupérer les images produites par notre logiciel.
Ătape 4 : anticiper les accĂšs rĂ©seau nĂ©cessaires
Automatic-Image-Converter n’a pas besoin de communiquer avec d’autres processus via le rĂ©seau.
On souhaite préparer une image de conteneur pour Simplestblog, notre logiciel de blog accessible par le web.
Ătape 1 : dĂ©finir le mode de configuration de lâimage
Simplestblog est un logiciel qui requiert un fichier de configuration pour fonctionner.
Petite subtilitĂ©, le logiciel ira chercher ce fichier de configuration Ă l’emplacement spĂ©cifiĂ© par la variable d’environnement SIMPLESTBLOG_SETTINGS_FILE.
On fait le choix que le fichier de configuration devra ĂȘtre fourni lors de la phase d’usage, et on fait le choix qu’il sera toujours fourni Ă un emplacement constant au sein du conteneur, Ă savoir l’emplacement /config.py.
Par consĂ©quent, on fixe une valeur constante /config.py dans la variable SIMPLESTBLOG_SETTINGS_FILE (ce qui signifie que l’on considĂšre que l’utilisateur n’aura pas Ă utiliser dĂ©finir variable).
Ătape 2 : dĂ©finir le point dâentrĂ©e
En supposant que l’image de conteneur ait pour rĂ©pertoire initial le rĂ©pertoire avec le code source de Simplestblog, la commande pour exĂ©cuter le logiciel prend la forme :
waitress-serve --call simplestblog:create_app
Il n’y a pas d’arguments particuliers Ă fournir, donc on peut garder la commande telle quelle.
Ătape 3 : anticiper les points de montage nĂ©cessaires
Simplestblog n’a pas d’Ă©tat Ă stocker sous forme de fichier (car il stocke son Ă©tat dans une base de donnĂ©es), et ne produit aucun fichier.
En revanche, comme Ă©voquĂ© plus haut, Simplestblog requiert un fichier de configuration Ă l’emplacement constant /config.py fixĂ© prĂ©cĂ©demment.
On documente donc pour notre image qu’un montage de fichier Ă l’emplacement /config.py est attendu lors de la phase d’usage.
Ătape 4 : anticiper les accĂšs rĂ©seau nĂ©cessaires
Simplestblog souhaite communiquer avec des processus extérieurs de deux maniÚres :
-
d’une part, Simplestblog Ă©coute sur le port rĂ©seau
5000et s’attend Ă ĂȘtre sollicitĂ© par des navigateurs webs (ex. Firefox) sur ce port. -
d’autre part, Simplestblog cherche Ă contacter une base de donnĂ©es compatible MySQL situĂ©e sur un rĂ©seau accessible ; plus prĂ©cisĂ©ment, Simplestblog se basera sur la valeur
MYSQL_DATABASE_HOSTdu fichier de configuration attendu pour savoir à quelle adresse réseau se connecter pour trouver une base de données, et sur la valeurMYSQL_DATABASE_PORTpour savoir sur quel port réseau se connecter.
On Ă©crit bien ces informations dans la documentation de l’image.
4. Utiliser Podman pour créer et gérer des images de conteneur
4.1. CrĂ©ation d’une image Ă partir d’un conteneur
Supposons qu’un conteneur temporaire ait Ă©tĂ© créé Ă partir d’une image dite "de base", puis que ce conteneur ait Ă©tĂ© modifiĂ© pour contenir un logiciel Ă dĂ©ployer ainsi que ses dĂ©pendances. La commande Ă utiliser pour crĂ©er une image de conteneur Ă partir de ce conteneur temporaire est la suivante :
$ podman container commit <nom du conteneur> \
<options> \
<nom donné>:<étiquette donnée>
avec :
-
<nom du conteneur>: le nom du conteneur à partir duquel on crée une nouvelle image, -
<nom donnĂ©>: le nom que l’on souhaite donner Ă cette nouvelle image, -
<Ă©tiquette donnĂ©e>l’Ă©tiquette que l’on souhaite donner Ă cette nouvelle image.
| S’il y avait dĂ©jĂ une image stockĂ©e localement avec le mĂȘme nom et la mĂȘme Ă©tiquette, elle est alors remplacĂ©e par la nouvelle image. |
Dans <options> nous allons en utiliser une seule appelée --change, qui permet de définir des métadonnées pour notre nouvelle image.
Plus précisément, nous allons utiliser trois variantes de cette option :
-
--change 'WORKDIR <rĂ©pertoire>': spĂ©cifie le rĂ©pertoire de dĂ©part Ă partir duquel le point d’entrĂ©e est exĂ©cutĂ©, -
--change 'CMD <point d’entrĂ©e>': spĂ©cifie le point d’entrĂ©e, c’est Ă dire la commande qui sera exĂ©cutĂ©e lorsqu’un conteneur sera créé Ă partir de cette nouvelle image, -
--change 'ENV <clĂ©>=<valeur>': affecteÂ<valeur>Ă une variable d’environnement<clĂ©>lors de l’exĂ©cution du point d’entrĂ©e.
On souhaite prĂ©parer une image jouet qui conteneurise l’utilitaire Unix figlet qui permet d’Ă©crire en art ASCII un message sur la ligne de commande.
On conçoit notre image de la maniÚre suivante :
-
l’image de base sera l’image officielle Ubuntu Linux en version 25.10, disponible sur le Docker Hub,
-
on installera la commande
figletavec le gestionnaire de paquetapt, -
on souhaite que l’utilisateur futur de l’image puisse spĂ©cifier un message Ă afficher Ă l’aide d’une variable d’environnement
MESSAGE.
On commence par préparer un conteneur temporaire :
$ podman container run -ti --name figlet_template docker.io/ubuntu:25.10
Dans ce conteneur temporaire, on installe figlet :
$ apt update
$ apt install figlet
C’Ă©tait l’unique Ă©lĂ©ment Ă ajouter pour notre image, on peut donc quitter l’interprĂ©teur de commande de notre conteneur temporaire :
# exit
Puis on peut utiliser commit pour créer une nouvelle image à partir de notre conteneur temporaire.
Lors de cette crĂ©ation d’image, on fixe un point d’entrĂ©e via la mĂ©tadonnĂ©e CMD qui exĂ©cute la commande figlet en lui demandant de lire la variable d’environnement MESSAGE :
$ podman container commit figlet_template \
--change 'CMD figlet $MESSAGE' \
figlet:v1
Suite à cette commande, nous avons créé une nouvelle image de conteneur stockée localement (dénoté localhost).
On peut alors utiliser notre image de la maniĂšre suivante, en n’oubliant pas de fixer une valeur Ă la variable d’environnement MESSAGE :
podman container run --rm --env MESSAGE="hello world" localhost/figlet:v1
_ _ _ _ _
| |__ ___| | | ___ __ _____ _ __| | __| |
| '_ \ / _ \ | |/ _ \ \ \ /\ / / _ \| '__| |/ _` |
| | | | __/ | | (_) | \ V V / (_) | | | | (_| |
|_| |_|\___|_|_|\___/ \_/\_/ \___/|_| |_|\__,_|
Automatic-Image-Converter est un logiciel développé en Java, il nous faut donc à minima un environnement fournissant la commande java.
Si on fait l’hypothĂšse que le logiciel n’a pas Ă©tĂ© prĂ©-compilĂ©, alors nous avons Ă©galementbesoin d’un environnement avec les commandes nĂ©cessaires pour cette compilation.
Le code de Automatic-Image-Converter repose sur l’outil Maven pour la compilation, il nous faut donc une image nous fournissant la commande maven.
On se rend sur la page de l’image officielle Maven, et on regarde les versions.
On souhaite Java en version 17, et on souhaite utiliser Eclipse Temurin comme distribution Java Ă la fois pour la compilation et l’exĂ©cution.
On choisit donc l’Ă©tiquette 3-eclipse-temurin-17 comme image de base pour notre conteneur temporaire :
$ podman container run -ti --name aic_template \
docker.io/maven:3-eclipse-temurin-17 \
bash
On choisit de dĂ©marrer explicitement notre conteneur temporaire avec le point d’entrĂ©e bash, et non avec la commande mvn qui est le point d’entrĂ©e par dĂ©faut de l’image maven.
|
En parallĂšle, dans un second terminal, on rĂ©cupĂšre le projet de dĂ©veloppement de Automatic-Image-Converter dans un rĂ©pertoire aic, puis on copie tout le code source au sein du conteneur Ă l’emplacement prĂ©vu :
$ podman container cp ./aic simplestblog_template:/install
De retour dans le conteneur, on peut vĂ©rifier que tout est bien arrivĂ© Ă l’emplacement prĂ©vu :
# cd /install
# ls
acceptance_testing Containerfile.nobuild Containerfile.twostages README.adoc
ansible Containerfile.singlestage pom.xml src
Puis on peut utiliser mvn pour Ă la fois installer les bibliothĂšques requises par Automatic-Image-Converter , et compiler Automatic-Image-Converter au passage :
# mvn package
Cette commande produit dans le conteneur le fichier /install/target/automatic-image-converter-1.0-SNAPSHOT.jar qui contient tout notre logiciel compilé avec ses dépendances.
Ă partir d’ici, notre conteneur contient exactement ce que l’on souhaite comme fichiers au sein de notre future image, Ă savoir :
-
un environnement Java,
-
le logiciel que l’on souhaitera dĂ©ployer (Ă savoir Automatic-Image-Converter),
-
les dépendances du dit logiciel (à savoir les bibliothÚques Java requises par Automatic-Image-Converter)
On peut donc quitter l’interprĂ©teur de commande de notre conteneur temporaire :
# exit
PrĂ©cĂ©demment, nous avons anticipĂ© la conception de notre image Automatic-Image-Converter avec un point d’entrĂ©e qui anticipe la dĂ©finition de certaines variables d’environnement en phase d’usage. On en dĂ©duit donc les mĂ©tadonnĂ©es suivantes :
WORKDIR /install
CMD java -jar target/automatic-image-converter-1.0-SNAPSHOT.jar /inputs /outputs $FORMAT $DURATION
Ainsi, Ă partir du conteneur temporaire simplestblog_template, on peut crĂ©er une image appelĂ©e simplestblog et Ă©tiquettĂ©e v1 Ă l’aide de la commande suivante :
$ podman container commit aic_template \
--change 'WORKDIR /install' \
--change 'CMD java -jar target/automatic-image-converter-1.0-SNAPSHOT.jar /inputs /outputs $FORMAT $DURATION' \
aic:v1
En supposant avoir préparé localements les répertoires /data/input_images et /data/input_images, on peut ensuite par exemple utiliser notre image de conteneur de la maniÚre suivante :
podman container run --name aic \
--detach \
--rm \
--mount type=bind,source="/data/input_images",target="/inputs" \
--mount type=bind,source="/data/output_images",target="/outputs" \
--env FORMAT="png" \
--env DURATION="5000" \
localhost/aic:v1
Simplestblog étant une application web développée en Python, il nous faut donc à minima un environnement fournissant la commande python.
On choisit d’utiliser l’image officielle Python comme image de base.
L’image en question est disponible sur le Docker Hub et on se rend sur sa page de description.
On souhaite une version de l’image qui contienne Python version 3, et qui soit aussi lĂ©gĂšre (slim) que possible.
On se dĂ©cide Ă utiliser l’Ă©tiquette 3-slim.
$ podman container run -ti --name simplestblog_template \
docker.io/python:3-slim \
bash
On choisit de dĂ©marrer explicitement notre conteneur Python avec le point d’entrĂ©e bash, et non avec l’interprĂ©teur Python qui est le point d’entrĂ©e par dĂ©faut de l’image docker.io/python.
|
En parallĂšle, dans un second terminal, on rĂ©cupĂšre le projet de dĂ©veloppement de Simplestblog dans un rĂ©pertoire simplestblog, puis on copie tout le code source situĂ© dans le sous-rĂ©pertoire src au sein du conteneur Ă l’emplacement prĂ©vu :
$ podman container cp simplestblog/src simplestblog_template:/install
De retour dans le conteneur, on peut vĂ©rifier que tout est bien arrivĂ© Ă l’emplacement prĂ©vu :
# cd /install
# ls
Containerfile Simplestblog.egg-info example instance reports simplestblog
LICENSE.rst dist htmlcov pyproject.toml requirements.txt tests
Puis on peut utiliser pip pour installer les bibliothĂšques Python requises par Simplestblog :
# pip install -r requirements.txt
Ă partir d’ici, notre conteneur contient exactement ce que l’on souhaite comme fichiers au sein de notre future image, Ă savoir :
-
un environnement Python,
-
le logiciel que l’on souhaitera dĂ©ployer (Ă savoir Simplestblog),
-
les dépendances du dit logiciel (à savoir les bibliothÚques Python requises par Simplestblog)
On peut donc quitter l’interprĂ©teur de commande de notre conteneur temporaire :
# exit
PrĂ©cĂ©demment, nous avons anticipĂ© la conception de notre image Simplestblog avec un point d’entrĂ©e et une constante fixĂ©e dans la variable d’environnement SIMPLESTBLOG_SETTINGS_FILE.
On en déduit donc les métadonnées suivantes :
WORKDIR /install
CMD waitress-serve --call simplestblog:create_app
ENV SIMPLESTBLOG_SETTINGS_FILE=/config.py
Ainsi, Ă partir du conteneur temporaire simplestblog_template, on peut crĂ©er une image appelĂ©e simplestblog et Ă©tiquettĂ©e v1 Ă l’aide de la commande suivante :
$ podman container commit simplestblog_template \
--change 'WORKDIR /install' \
--change 'CMD waitress-serve --call simplestblog:create_app' \
--change 'ENV SIMPLESTBLOG_SETTINGS_FILE=/config.py' \
simplestblog:v1
En supposant que l’on ait prĂ©parĂ© localement un fichier de configuration /data/simplestblog/test_config.py, on peut par exemple utiliser notre image de conteneur de la maniĂšre suivante :
podman container run --name simplestblog_app \
--detach \
--rm \
--mount type=bind,source=/data/simplestblog/test_config.py,target=/config.py \
--network simplestblog_network \
--publish 8100:5000 \
localhost/simplestblog:v1
4.2. Lister, inspecter des images
Pour lister toutes les images présentes dans le stockage local :
$ podman image list
Suite Ă la construction de l’image de Simplestblog prĂ©cĂ©demment, on liste les images prĂ©sentes sur le stockage local :
$ podman image list
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/simplestblog v1 1bd95c71ec04 7 seconds ago 278 MB
docker.io/library/python 3-slim c1c23a6632a4 13 days ago 136 MB
On observe que deux images sont présentes :
-
La premiĂšre est l’image Simplestblog que nous avons créé, avec pour nom
simplestbloget comme étiquettev1 -
La seconde est l’image Python qui a Ă©tĂ© tĂ©lĂ©chargĂ©e lors de l’instruction
FROM, et qui a Ă©tĂ© utilisĂ©e comme base pour construire l’image Simplestblog.
Pour inspecter tous les dĂ©tails d’une image du stockage local, on peut faire :
$ podman image inspect <référence d'image>
Bien que trĂšs utile dans certains contextes, cette commande produit un rĂ©sultat en JSON trĂšs verbeux et assez peu lisible. Ă n’utiliser que lorsqu’on souhaite vĂ©rifier certaines propriĂ©tĂ©s d’une image (format de stockage, variables d’environnement, etc.).
4.3. Interagir avec un registre distant
Si on souhaite interagir avec un registre de conteneurs distant avec accĂšs restreint, il est d’abord nĂ©cessaire de s’authentifier avec un compte utilisateur auprĂšs de ce registre.
Pour s’authentifier auprĂšs d’un registre distant :
$ podman login <nom d'hĂŽte registre distant>
On doit ensuite saisir son nom d’utilisateur et son mot de passe. Si le login est validĂ©, alors toutes les futures commandes Podman pourront utiliser le registre privĂ©.
| Cette authentification n’est pas permanente et ne dure que le temps d’une session utilisateur Linux. Il sera par exemple nĂ©cessaire de refaire cette authentification Ă chaque sĂ©ance de TP. |
Le registre d’images du Gitlab Nantes UniversitĂ© a le fonctionnement suivant :
-
Chaque projet de dĂ©veloppement peut hĂ©berger ses propres images de conteneurs, visibles dans l’interface Ă l’aide du menu DĂ©ploiement â Registre de conteneur.
-
Pour pouvoir envoyer une image de conteneur au sein d’un projet, il est nĂ©cessaire d’utiliser un compte Gitlab qui possĂšde le statut Developer, Maintainer ou Owner au sein du projet.
-
Pour pouvoir tĂ©lĂ©charger une image de conteneur d’un projet, il y a deux cas de figure :
-
Si le projet est public, alors les images sont tĂ©lĂ©chargeables par n’importe qui sans besoin de compte Gitlab au prĂ©alable.
-
Si le projet est privé, alors seul un membre du projet peut télécharger une image du projet.
-
Ainsi, pour que vous puissiez correctement envoyer et rĂ©cupĂ©rer des images, en particulier celles de vos projets de dĂ©veloppement privĂ©s, il vous faut d’abord faire :
$ podman login docker-registry.univ-nantes.fr
puis saisir votre identifiant et mot de passe université.
Pour télécharger manuellement une image distante vers le stockage local :
$ podman image pull <reference d'image>
Pour publier son image sur un registre distant :
$ podman image push <reference d'image locale> \
<chemin d'image distante>
Un push nĂ©cessite toujours un login prĂ©alable, et nĂ©cessite d’avoir les droits nĂ©cessaires pour dĂ©poser l’image Ă l’emplacement indiquĂ© dans le chemin d’image distante.
|
On souhaite publier l’image simplestblog:v1 construite prĂ©cĂ©demment.
On suppose avoir dĂ©jĂ fait l’authentification nĂ©cessaire auprĂšs du registre de conteneur de Nantes UniversitĂ©.
Le projet de développement de Simplestblog est hébergé sur le Gitlab Nantes Université et est visible sur cette page.
Le chemin complet au sein du Gitlab (et, par extension, au sein du registre de conteneurs) est developpement_exploitation/resources/simplestblog.
Ă l’aide d’un compte utilisateur qui a suffisamment de droits dans ce projet, on exĂ©cute la commande suivante :
$ podman image push simplestblog:v1 \
docker-registry.univ-nantes.fr/gl/developpement_exploitation/resources/simplestblog:v1
Suite Ă cela, sur la page du projet sur le Gitlab Nantes UniversitĂ©, on se rend sur la page DĂ©ploiement â Registre de conteneur, et on constate la prĂ©sence de l’Ă©tiquette v1 au cĂŽtĂ© des autres versions disponibles de l’image :
4.4. Supprimer des images
Pour supprimer une image du stockage local :
$ podman image rm <référence image>
| Cette commande Ă©chouera s’il existe localement au moins un conteneur instance de l’image rĂ©fĂ©rencĂ©e. Il faudra donc d’abord supprimer les conteneurs concernĂ©s. |
Pour supprimer toutes les images actuellement non utilisées par des conteneurs :
$ podman image prune --all
5. Références
-
Documentation officielle Docker (consultée le 08/09/2023)
-
Documentation officielle Podman (consultée le 08/09/2023)