đŸ’» TP : Scripter la conteneurisation d’un logiciel

1. Présentation et objectifs

L’objectif de ce TP est d’apprendre Ă  utiliser le language Containerfile ainsi que l’outil Podman pour crĂ©er de nouvelles images de conteneurs.

Tout pour tous les TPs, lorsque le sujet de TP vous propose d’exĂ©cuter une commande, il est demandĂ© que vous arriviez Ă  comprendre tout ce que comporte cette commande. Prenez le temps de bien lire et dĂ©cortiquer chaque commande qui vous est proposĂ©e, et n’hĂ©sitez pas Ă  poser des questions.

2. Préparatifs

Ce TP est similaire au TP prĂ©cĂ©dent sur le principe, Ă  savoir la crĂ©ation et la publication d’images. La seule diffĂ©rence est que la crĂ©ation d’images va cette fois se faire avec Containerfile.

Pour la publication d’images, vous allez pouvoir rĂ©utiliser le projet Gitlab developpement_exploitation-tp-images créé lors du TP prĂ©cĂ©dent.

Il vous faut Ă©galement ne pas oublier de vous rĂ©-authentifier auprĂšs du registre de conteneurs pour les exercices qui vous demandent de publier l’image produite :

$ podman login docker-registry.univ-nantes.fr

3. Tutoriel : image cowsay via un Containerfile

3.1. Rappel

Dans le TP précédent, nous avions vu comme premier exemple comment créer une image de conteneur qui met à disposition la commande cowsay.

Dans ce tutoriel, nous allons refaire exactement la mĂȘme chose, mais en l’automatisant Ă  l’aide d’un script Containerfile.

3.2. Premier Containerfile avec FROM et RUN

Sur l’environnement de dĂ©ploiement, crĂ©ez un nouveau rĂ©pertoire tutoriel-cowsay-containerfile, et prĂ©parez le Containerfile suivant :

FROM docker.io/ubuntu:24.04

RUN apt update
RUN apt install -y cowsay

On peut observer l’ajout de l’option -y lors de l’appel Ă  apt install. La raison est que durant l’exĂ©cution d’un Containerfile, il n’est pas possible d’interagir avec le constructeur d’image. Or, par dĂ©faut, la commande apt peut demander Ă  l’utilisateur de confirmer l’installation d’un paquet Ă  l’aide de la touche clavier y (pour yes) ou n (pour no). Pour Ă©viter cela, l’option -y indique qu’il faut automatiquement rĂ©pondre par y Ă  toutes les questions posĂ©es par apt.

Faites ensuite appel Ă  Podman pour crĂ©er une nouvelle image avec pour nom tutoriel-cowsay et pour Ă©tiquette v3 :

$ podman image build --tag tutoriel-cowsay:v3 .
La derniĂšre partie d’une commande podman image build doit ĂȘtre le chemin vers un rĂ©pertoire dit de contexte. Dans notre cas, il suffit donc de pointer vers le rĂ©pertoire tutoriel-cowsay-containerfile, qui est normalement ici votre rĂ©pertoire courant, donc ".". Si le rĂ©pertoire de contexte possĂšde un Containerfile, il sera utilisĂ© par dĂ©faut, sauf si l’option --file est spĂ©cifiĂ©e.

Vous verrez alors apparaĂźtre une sortie textuelle complĂšte de ce qui est rĂ©alisĂ© pour crĂ©er l’image. Chaque instruction du Containerfile apparaĂźt sous la forme d’une Ă©tape (STEP).

Une fois l’image construite, vĂ©rifiez qu’elle est bien prĂ©sente dans votre stockage d’image local :

$ podman image list

On notera que la colonne REPOSITORY indique la rĂ©fĂ©rence d’image, qui dans notre cas commence par localhost puisque l’image est sur le stockage local.

Il est possible que vous ayez Ă©galement dans cette liste un reliquat d’images tĂ©lĂ©chargĂ©es dans les prĂ©cĂ©dents exercices, ce qui est normal.

Il ne nous reste plus qu’Ă  tester notre nouvelle image, on peut donc faire :

$ podman container run --rm -ti localhost/tutoriel-cowsay:v3

Comme lors du TP prĂ©cĂ©dent, on se retrouve dans un interprĂ©teur de commandes au sein du conteneur. On peut alors directement exĂ©cuter la commande souhaitĂ©e, sans avoir Ă  l’installer au prĂ©alable :

$ /usr/games/cowsay "Bonjour depuis notre image construite avec un Containerfile !"

3.3. Ajout d’un point d’entrĂ©e avec CMD

Comme la derniĂšre fois, on souhaite maintenant amĂ©liorer notre image en modifiant quel logiciel est exĂ©cutĂ© lors du dĂ©marrage d’un conteneur créé avec l’image. Cela nĂ©cessite de spĂ©cifier un point d’entrĂ©e pour l’image Ă  l’aide de l’instruction CMD dans le Containerfile.

Il est possible dans une instruction CMD de faire rĂ©fĂ©rence Ă  une variable d’environnement avec la syntaxe $VARIABLE. On prĂ©pare donc la deuxiĂšme version suivante pour notre Containerfile, qui spĂ©cifie un point d’entrĂ©e avec la commande cowsay prenant comme argument le contenu d’une nouvelle variable d’environnement MESSAGE :

FROM docker.io/ubuntu:24.04

RUN apt update
RUN apt install -y cowsay

CMD /usr/games/cowsay $MESSAGE

À l’aide de ce Containerfile modifiĂ©, construisez une nouvelle image de conteneur, cette fois-ci avec l’Ă©tiquette v4 :

$ podman image build --tag tutoriel-cowsay:v4 .

On peut vĂ©rifier que l’image est bien créée Ă  nouveau Ă  l’aide de la commande :

$ podman image list

On peut ainsi dĂ©sormais exĂ©cuter un conteneur de la sorte :

$ podman container run --rm \
                       --env MESSAGE="Re-bonjour depuis notre nouvelle image !" \
                       localhost/tutoriel-cowsay:v4

Et voilà en fonctionnement une construction automatisée de notre image paramétrable !

4. Exercice : image Asciidoctor via Containerfile

Refaites l’exercice Asciidoctor du TP prĂ©cĂ©dent, mais cette fois-ci construisez votre image de conteneur Ă  l’aide d’un Containerfile.

5. Tutoriel : image site web nginx via Containerfile

5.1. Rappel

Pour rappel, dans le TP prĂ©cĂ©dent nous avions prĂ©parĂ© une image de conteneur contenant un petit site web prĂšs Ă  ĂȘtre dĂ©ployĂ©. Nous allons dans ce tutoriel accomplir la mĂȘme chose, mais Ă  l’aide d’un Containerfile.

5.2. Containerfile avec FROM, RUN et COPY

L’objectif ici est de crĂ©er une image de conteneur dans laquelle se trouve directement Ă  la fois le logiciel nginx et le site web qu’on souhaite dĂ©ployer.

Pour accomplir cela, il nous faut, lors de la crĂ©ation de l’image, s’assurer que notre site web (qui contient Ă  minima un fichier index.html) soit copiĂ© dans le rĂ©pertoire /usr/share/nginx/html/ de l’image, car c’est Ă  cet emplacement que nginx va charger le site qu’il rendra accessible.

Au sein de l’image nginx, le contenu par dĂ©faut de /usr/share/nginx/html/ n’est pas vide, car il contient une page d’accueil d’exemple, qui ne nous intĂ©resse pas ! Il va donc nous falloir remplacer ce rĂ©pertoire par le contenu de notre choix.

Sur l’environnement de dĂ©ploiement, crĂ©ez un nouveau rĂ©pertoire tutoriel-nginx. Dans ce rĂ©pertoire, mettez le HTML que vous aviez gĂ©nĂ©rĂ© Ă  l’aide d’Asciidoctor dans l’exercice prĂ©cĂ©dent, et renommez ce fichier en index.html. Ensuite, rendez-vous dans le rĂ©pertoire tutoriel-nginx et prĂ©parez le Containerfile suivant :

FROM docker.io/nginx:1.25

RUN rm /usr/share/nginx/html/*

COPY ./*.html /usr/share/nginx/html/index.html

On observe que :

  • À l’aide de RUN, une commande rm est utilisĂ©e pour supprimer le contenu du rĂ©pertoire /usr/share/nginx/html/, afin de supprimer la page d’accueil d’exemple qui est fournie d’office dans l’image nginx.

  • À l’aide de COPY, On ajoute Ă  l’image tous les fichiers HTML du rĂ©pertoire tutoriel-nginx, au cas oĂč notre site comporte plusieurs pages.

Il est possible d’Ă©crire un Containerfile Ă©quivalent Ă  celui ci-dessus en utilisant la commande WORKDIR pour changer le rĂ©pertoire courant, qui permet de simplifier les commandes RUN et ADD qui suivent. N’hĂ©sitez pas Ă  essayer !

Construisez une image de conteneur avec la commande suivante :

$ podman image build --tag tutoriel-nginx:2 .

Enfin, testez votre image en crĂ©ant un conteneur :

$ podman container run --rm \
                       --detach \
                       --name nouveau_serveur_web \
                       --publish <mon port réseau>:80 \
                       localhost/tutoriel-nginx:2

VĂ©rifiez que votre dĂ©ploiement fonctionne en accĂ©dant depuis un navigateur Ă  l’adresse http://podman:<mon port rĂ©seau> : normalement votre HTML s’affiche comme prĂ©vu !

Une fois ce tutoriel terminĂ©, n’oubliez pas d’arrĂȘter et de supprimer le conteneur créé.

6. Exercice : crĂ©er une image pour Web Calculator (Python)

6.1. ÉnoncĂ©

On souhaite crĂ©er une image de conteneur pour un logiciel fraĂźchement dĂ©veloppĂ© appelĂ© Web Calculator. C’est une application web dĂ©veloppĂ©e en Python, dont le code source est disponible sur le projet Gitlab suivant.

Une fois exĂ©cutĂ©e, l’application peut ĂȘtre accĂ©dĂ©e via un navigateur web, et fournit une interface pour faire des calculs arithmĂ©tiques entre deux nombres (addition, soustraction, etc.).

Lisez la documentation de l’application, et en particulier les sections 3 et 4. On y trouve des informations importantes, notamment :

  • Le logiciel nĂ©cessite un certain nombre de dĂ©pendances Python.

  • Ces dĂ©pendances peuvent ĂȘtre installĂ©es Ă  l’aide de l’utilitaire pip.

  • Une commande uvicorn permet de dĂ©marrer le logiciel.

  • Le logiciel nĂ©cessite le port rĂ©seau 8000 pour recevoir des connexions.

La documentation fait rĂ©fĂ©rence Ă  un concept Python appelĂ© venv. C’est une maniĂšre pratique pour crĂ©er des environnements Python dans lesquelles on installe des dĂ©pendances spĂ©cifiques Ă  un dĂ©veloppement ou un dĂ©ploiement particulier. Dans notre cas, nous pouvons ignorer l’utilisation de venv car cela n’est pas nĂ©cessaire dans un conteneur, qui fourni dĂ©jĂ  un environnement isolĂ© adaptĂ©.

6.2. Préparatifs

Vous allez avoir besoin de rĂ©cupĂ©rer le code source du logiciel afin de l’ajouter dans votre image de conteneur. Pour cela, le plus simple est d’utiliser l’utilitaire git de la maniĂšre suivante :

$ git clone <URL git>

avec <URL git> l’URL git du projet que l’on souhaite rĂ©cupĂ©rer.

Pour obtenir l’URL dit d’un projet Gitlab, on clique sur le bouton "Code" et on copie le contenu "Cloner avec HTTPS". On peut ensuite coller l’URL dans un terminal pour faire notre git clone.

Par exemple pour le projet web calculator on peut faire :

[sur l’environnement de dĂ©ploiement distant]
$ git clone https://gitlab.univ-nantes.fr/gl/developpement_exploitation/resources/web-calculator.git

ce qui va crĂ©er un rĂ©pertoire web-calculator oĂč sera tĂ©lĂ©chargĂ© tout le code source du projet.

6.3. Questions

Pour récupérer le code source du projet Gitlab, vous pouvez suivre les instructions dédiées de la notice Gitlab.
  1. PrĂ©parez un Containerfile permettant de crĂ©er une image Web Calculator. Pour cela, posez-vous les questions suivantes :

    1. Quels outils doivent ĂȘtre prĂ©sents dans notre image de base ? Par consĂ©quent, quelle image de base choisir ?

      Pour choisir une image de base, n’hĂ©sitez pas Ă  relire la section correspondante dans le chapitre sur les images de conteneurs.
    2. Quels fichiers faut-il mettre dans l’image afin d’exĂ©cuter le logiciel ?

    3. Quelles commandes faut-il exĂ©cuter lors de la construction de l’image ?

    4. Quelle mĂ©tadonnĂ©e est nĂ©cessaire pour le point d’entrĂ©e ?

  2. CrĂ©ez une image en exĂ©cutant votre Containerfile Ă  l’aide de Podman. On souhaite que notre image se nomme webcalculator et ait pour Ă©tiquette dev.

  3. PrĂ©parez une commande pour crĂ©er un conteneur Ă  l’aide de votre image créée localement, puis dĂ©ployez votre application sur le serveur de dĂ©ploiement.

  4. Testez votre application Ă  l’aide d’un navigateur.

  5. Publiez votre image au sein de votre projet Gitlab.

7. Exercice : crĂ©er une image webdav-embedded-server (Java)

7.1. ÉnoncĂ©

On souhaite crĂ©er une image de conteneur pour le logiciel webdav-embedded-server, dĂ©veloppĂ© en Java, dont le code source est disponible au sein d’un projet sur le Gitlab UniversitĂ©.

Ce logiciel permet d’exĂ©cuter un serveur de stockage de fichiers, sur lequel il est possible de se connecter Ă  l’aide du protocole Webdav. Ce protocole est aujourd’hui trĂšs rĂ©pandu et de nombreux explorateurs de fichiers sont capables d’accĂ©der Ă  distance au contenu d’un serveur Webdav, afin de lire, modifier, crĂ©er ou supprimer des fichiers.

Si on analyse le contenu du projet on dĂ©couvre plusieurs Ă©lĂ©ments importants :

  • On peut voir la prĂ©sence d’un fichier build.gradle, qui signifie que la compilation du code doit se faire avec l’outil Gradle. Si on fouille dans le fichier build.gradle, on dĂ©couvre qu’une commande Gradle intitulĂ©e fatJar est disponible, et permet de compiler le code du logiciel au sein d’un fichier .jar qui embarque automatiquement toutes les dĂ©pendances du logiciel − trĂšs pratique pour un dĂ©ploiement !

  • On peut voir dans le README une description sommaire du mode Standalone du logiciel, qui permet de dĂ©marrer un serveur. On peut voir que diffĂ©rentes options sont disponibles pour lancer l’application, notamment --credentials qui permet de spĂ©cifier un compte utilisateur pour se connecter au serveur, et --port qui permet de spĂ©cifier le port Ă  utiliser pour se connecter Ă  l’application (par dĂ©faut, 8080). AprĂšs les options, il faut spĂ©cifier le chemin du rĂ©pertoire dans lequel le serveur Webdav stockera ses fichiers.

Si on met tout cela bout Ă  bout, cela signifie qu’on peut compiler notre application Ă  l’aide de la commande :

$ gradle fatJar

Cela produira normalement un fichier build/libs/webdav-embedded-server-0.2.1-SNAPSHOT-fatjar.jar.

Malheureusement, le serveur de dĂ©ploiement de l’UniversitĂ© possĂšde une contrainte qui va entraver l’usage de Gradle : l’usage obligatoire d’un proxy HTTP pour toute connexion HTTP rĂ©alisĂ©e (donc pour tout tĂ©lĂ©chargement de fichier). Or, Gradle a besoin de tĂ©lĂ©charger des fichiers pour rĂ©cupĂ©rer toutes les dĂ©pendances Java du projet
 !

Jusqu’ici le problĂšme ne s’est pas prĂ©sentĂ© durants les TPs car le serveur de dĂ©ploiement est bien configurĂ©, et possĂšde une variable d’environnement standard appelĂ©e https_proxy qui est utilisĂ©e automatiquement par tous les logiciels pour utiliser le proxy de maniĂšre transparente. Ainsi, on peut gĂ©nĂ©ralement ignorer la prĂ©sence du proxy, et laisser les logiciels l’utiliser par eux-mĂȘme sans que nous ayons Ă  faire quoi que ce soit.

Mais Gradle n’est pas capable d’utiliser la variable https_proxy ! Il est nĂ©cessaire de lui donner cette information via deux options :

  • -Dhttps.proxyHost=<nom d’hĂŽte proxy HTTP>

  • -Dhttps.proxyPort=<port rĂ©seau proxy HTTP>

À l’UniversitĂ©, le serveur de proxy HTTP est accessible avec le nom d’hĂŽte proxy.ensinfo.sciences.univ-nantes.prive et avec le port 3128.

Si on met tout cela bout Ă  bout, il est donc dans notre cas nĂ©cessaire d’appeler Gradle de la sorte :

$ gradle -Dhttps.proxyHost=proxy.ensinfo.sciences.univ-nantes.prive \
         -Dhttps.proxyPort=3128 fatJar

Ensuite, depuis le rĂ©pertoire build/libs, on peut lancer le serveur avec la commande :

$ java -jar webdav-embedded-server-0.2.1-SNAPSHOT-fatjar.jar
            --credentials "<utilisateur>:<mot de passe>"

Et le serveur Webdav dĂ©marrera en Ă©coutant sur le port 8080, et n’autorisera que les informations de connections spĂ©cifiĂ©es par --credentials.

Contraintes Ă  respecter : Lors de la crĂ©ation d’un conteneur Ă  partir votre l’image, on souhaite pouvoir spĂ©cifier :

  • un nom d’utilisateur et un mot de passe qui seront les informations de connexion acceptĂ©es par le serveur Webdav.

  • un emplacement de l’environnement d’accueil dans lequel le serveur stockera ses fichiers.

7.2. Préparatifs

RĂ©cupĂ©rez le code source du logiciel Ă  l’aide de git clone.

7.3. Questions (crĂ©ation de l’image)

Pour récupérer le code source du projet Gitlab, vous pouvez suivre les instructions dédiées de la notice Gitlab.
  1. PrĂ©parez un Containerfile permettant de crĂ©er une image webdav-embedded-server. Pour cela, posez-vous les questions suivantes :

    1. Quels outils doivent ĂȘtre prĂ©sents dans notre image de base ? Par consĂ©quent, quelle image de base choisir ?

    2. Quels fichiers faut-il mettre dans l’image afin de compiler le logiciel ?

    3. Quels fichiers faut-il mettre dans l’image afin d’exĂ©cuter le logiciel ? D’oĂč provient ce fichier ?

    4. Quelles commandes faut-il exĂ©cuter lors de la construction de l’image ?

    5. Par quels mécanismes gérer les deux contraintes posées plus haut ?

    6. Quelle mĂ©tadonnĂ©e est nĂ©cessaire pour le point d’entrĂ©e ?

  2. CrĂ©ez une image en exĂ©cutant votre Containerfile Ă  l’aide de Podman. On souhaite que notre image se nomme webdavserver et ait pour Ă©tiquette latest.

  3. PrĂ©parez une commande pour crĂ©er un conteneur Ă  l’aide de votre image créée localement, puis dĂ©ployez votre application sur le serveur de dĂ©ploiement.

  4. Testez votre application de la sorte :

    1. Sur votre poste de travail linux, ouvrez l’application Fichiers (que vous utilisez quotidiennement pour accĂ©der Ă  vos fichiers).

    2. Utilisez le raccourci clavier CTRL+L afin d’accĂ©der Ă  la barre d’adresse en haut de l’a fenĂȘtre.

    3. Dans cette barre d’adresse, saisissez dav://podman:<port rĂ©seau>, afin de vous connecter Ă  votre serveur Webdav dĂ©ployĂ© sur le serveur de dĂ©ploiement. Saisissez les informations de connexion demandĂ©es, et validez. Si vous n’avez pas de message d’erreur, vous ĂȘtes bien connectĂ© !

    4. Tentez de copier un fichier de votre choix au sein de votre serveur Webdav.

    5. VĂ©rifiez que le fichier copiĂ© apparaĂźt bien dans l’emplacement du serveur de dĂ©ploiement oĂč le serveur stocke ses fichiers.

  5. Enfin, publiez votre image au sein de votre projet Gitlab.

7.4. Questions (amĂ©lioration de l’image)

Il est conseillĂ© (mais pas indispensable) de revenir sur ces questions "avancĂ©es" uniquement aprĂšs voir fini l’exercice WordcloudGenerator qui suit, ou bien pendant les longs temps d’attente dĂ»s Ă  l’installation de paquets durant l’exercice WordcloudGenerator.
  1. Quelle est la taille de l’image webdav-embedded-server que vous avez produite ?

  2. Qu’est-ce que qui peut expliquer la taille occupĂ©e par l’image ?

  3. Quelle stratĂ©gie Ă©tudiĂ©e en cours permettrait de rĂ©duire la taille de l’image ?

  4. Proposez un nouveau Containerfile qui mette en Ɠuvre cette stratĂ©gie, et comparez la taille de l’image obtenue avec la premiĂšre version.

Si vous avez dĂ©jĂ  mis en place cette stratĂ©gie − dĂ©jĂ , bravo ! − vous pouvez bien sĂ»r sauter cette partie.

8. Exercice : crĂ©er une image WordcloudGenerator (langage R)

8.1. ÉnoncĂ©

On souhaite crĂ©er une image de conteneur pour le logiciel WordcloudGenerator dĂ©veloppĂ© en R, dont le code source est lĂ  aussi disponible au sein d’un projet sur le Gitlab UniversitĂ©.

Ce logiciel permet de construire un nuage de mots Ă  partir d’un fichier texte simple. Il s’exĂ©cute sous la forme d’une application web qui peut ĂȘtre accĂ©dĂ©e depuis un navigateur. L’interface permet d’envoyer un fichier .txt et de sĂ©lectionner le nombre de mots devant apparaĂźtre dans le nuage.

Lisez la documentation technique du projet. On peut y trouver les informations utiles suivantes :

  • Le logiciel nĂ©cessite un ensemble de paquets R.

  • Le logiciel nĂ©cessite Ă©galement une bibliothĂšque logicielle C appelĂ©e libxml2.

  • Une commande simple est fournie pour exĂ©cuter le logiciel.

Installer un paquet R

Pour installer un paquet R dans un environnement donnĂ© oĂč R est dĂ©jĂ  installĂ©, on peut utiliser la commande suivante :

$ Rscript -e 'install.packages("<nom du package>")'
Installer un paquet R peut prendre beaucoup de temps ! N’hĂ©sitez pas Ă  faire la fin de l’exercice prĂ©cĂ©dent pendant la longue construction de votre image.

8.2. Préparatifs

RĂ©cupĂ©rez le code source du logiciel Ă  l’aide de git clone.

8.3. Questions

Pour récupérer le code source du projet Gitlab, vous pouvez suivre les instructions dédiées de la notice Gitlab.
  1. PrĂ©parez un Containerfile permettant de crĂ©er une image WordcloudGenerator. Pour cela, posez-vous les questions suivantes :

    1. Quels outils doivent ĂȘtre prĂ©sents dans notre image de base ? Par consĂ©quent, quelle image de base choisir ?

    2. Comment faire pour installer la bibliothĂšque logicielle C nĂ©cessaire au sein de l’image de base choisie ?

      Indice : vous pouvez allez voir quelle image de base a Ă©tĂ© utilisĂ©e pour construire l’image de base que vous souhaitez utiliser, cela peut vous aider Ă  savoir quel utilitaire de gestion de dĂ©pendance (apt, ou apk, ou dnf, ou autre) utiliser !
    3. Quels fichiers faut-il mettre dans l’image afin d’exĂ©cuter le logiciel ?

    4. Quelles commandes faut-il exĂ©cuter lors de la construction de l’image ?

    5. Quelle mĂ©tadonnĂ©e est nĂ©cessaire pour le point d’entrĂ©e ?

  2. CrĂ©ez une image en exĂ©cutant votre Containerfile Ă  l’aide de Podman. On souhaite que notre image se nomme wordcloudgenerator et ait pour Ă©tiquette v1.

  3. PrĂ©parez une commande pour crĂ©er un conteneur Ă  l’aide de votre image créée localement, puis dĂ©ployez votre application sur le serveur de dĂ©ploiement.

  4. Testez votre dĂ©ploiement Ă  l’aide d’un navigateur. Vous aurez pour cela besoin d’un fichier texte avec du contenu Ă  analyser. Vous pouvez par exemple utiliser le contenu du livre The Adventures of Sherlock Holmes, ou encore le contenu du livre Moby Dick.

  5. Enfin, publiez votre image au sein de votre projet Gitlab.