Skip to content

Podman et la conteneurisation

Podman est un outil open source de gestion de conteneurs qui permet de créer, gérer et exécuter des conteneurs sans nécessiter de démon en arrière-plan. Contrairement à Docker, Podman fonctionne en mode rootless, ce qui améliore la sécurité en permettant aux utilisateurs non privilégiés de gérer des conteneurs.

Pourquoi Podman ?

  • Rootless : Podman peut être exécuté sans privilèges root, ce qui réduit les risques de sécurité.
  • Compatibilité Docker : Podman utilise le même format d'image que Docker, ce qui facilite la transition.
  • Architecture sans deamon : À comparer a Docker qui utilise un processus (deamon) dockerd, Podman n'a pas de deamon en arrière-plan, ce qui simplifie la gestion des ressources.
  • Podman Desktop : Une interface graphique pour gérer les conteneurs Podman, facilitant l'utilisation pour les utilisateurs moins expérimentés. Gratuit et open source.

Installation de Podman

Installation Windows

Prérequis :

  • WSL2 (Windows Subsystem for Linux)
  • Activer la virtualisation dans le BIOS

Sans Podman Desktop :

Installer Podman CLI via leur site web : Podman

Simplement suivre les instructions d'installation pour Windows.

Avec Podman Desktop : Télécharger Podman Desktop depuis leur site officiel : Podman Desktop

Suivre les instructions d'installation. Lors de la première ouverture, vous devriez voir une bannière comme celle-ci indiquant que Podman Desktop a besoin de configuration supplémentaire.

first page meme

Cela vous proposera d'installer Podman CLI si ce n'est pas déjà fait, et de configurer le backend WSL2 (l'option wsl2 est sélectionnée par défaut). Suivre les instructions, cela devrait prendre quelques minutes.

À la fin, assurer vous de garder l'option "Autostart Podman engine when launching Podman Desktop", cela vous évitera d'avoir a démarré podman a l'ouverture de podman desktop.

Information ❗

Vous allez pouvoir désactiver l'ouverture automatique de Podman Desktop au démarrage de Windows dans les paramètres de l'application.

Il se peut que l'application vous demande d'installer l'extension Compose. Je vous le recommande, cela peut être très pratique pour utiliser plusieurs conteneurs simultanément. Le meilleur exemple est lorsqu'on doit utiliser une base de donnée.

Utilisation de Podman Desktop

L'interface de Podman Destkop ressemble à ceci :

first page meme

Dans le menu de gauche, vous allez pouvoir accéder aux différentes sections de l'application. Les plus importantes seront Container et Images. Voici en détail le fonctionnement de chacune de ces sections.

Images

Qu'est-ce qu'une image?

Dans le domaine de la conteneurisation, une image est un package léger, autonome et exécutable qui contient tout le nécessaire pour exécuter une application, y compris le code, les bibliothèques, les dépendances et les configurations système. Les images sont utilisées pour créer des conteneurs, qui sont des instances en cours d'exécution de ces images.

La configuration de l'image sera stockée dans un fichier texte appelé Containerfile ou Dockerfile (Dockerfile est le nom historique, Podman supporte les deux noms). Ce fichier contient une série d'instructions qui définissent comment construire l'image.

Une image se construit comme ceci :

  • Choix de l'image de base : Une image de base est choisie en fonction des besoins de l'application. Par exemple, une image de base peut être une distribution Linux minimale comme Alpine, Ubuntu, ou CentOS, ou une image spécifique à un langage de programmation comme Node.js, Python, etc.
  • Ajout des dépendances : Les dépendances nécessaires à l'application sont installées dans l'image. Cela peut inclure des bibliothèques, des outils, des packages, etc.
  • Copie du code source : Le code source de l'application est copié dans l'image.
  • Configuration : Des configurations supplémentaires peuvent être définies, telles que les variables d'environnement, les ports exposés, les commandes à exécuter au démarrage, etc.

Écriture d'un Containerfile (image)

Afin d'écrire une image, via un Containerfile, il faut suivre une série d'instructions. Voici les instructions les plus courantes utilisées dans un Containerfile :

  • FROM : Spécifie l'image de base à utiliser pour construire l'image.
  • RUN : Exécute une commande dans le conteneur lors de la construction de l'image.
  • COPY : Copie des fichiers ou des répertoires depuis l'hôte vers le conteneur.
  • ADD : Similaire à COPY, mais avec des fonctionnalités supplémentaires comme l'extraction d'archives.
  • WORKDIR : Définit le répertoire de travail pour les instructions suivantes.
  • ENV : Définit des variables d'environnement.
  • EXPOSE : Indique les ports que le conteneur écoutera
  • CMD : Spécifie la commande à exécuter lorsque le conteneur démarre.

De façons générale, on commence toujours l'écriture d'un Containerfile par l'instruction FROM, qui définit l'image de base. Ensuite, on ajoute les instructions nécessaires pour configurer l'image selon les besoins de l'application. Ensuite, cela va varier de vos besoins spécifiques.

Voici un exemple simple de Containerfile pour une application Python :

Dockerfile
# Étape 1 : Utiliser une image de base Python
FROM python:3.11

# Étape 2 : Définir le répertoire de travail
WORKDIR /app

# Étape 3 : Copier le fichier des dépendances
COPY requirements.txt .

# Étape 4 : Installer les dépendances (--no-cache-dir pour éviter de stocker les fichiers temporaires)
RUN pip install --no-cache-dir -r requirements.txt

# Étape 5 : Copier le code source de l'application
COPY . .

# Si nécessaire, exposer un port
# EXPOSE 5000
# Si nécessaire, définir un point d'entrée
# CMD ["python", "app.py"]

Explication des étapes :

  1. FROM python:3.11 : Utilise l'image officielle Python 3.11 comme image de base.
  2. WORKDIR /app : Définit le répertoire de travail à /app dans le conteneur.
  3. COPY requirements.txt . : Copie le fichier requirements.txt depuis l'hôte vers le répertoire de travail du conteneur.
  4. RUN pip install --no-cache-dir -r requirements.txt : Installe les dépendances Python listées dans requirements.txt.
  5. COPY . . : Copie tout le code source de l'application depuis l'hôte vers le répertoire de travail du conteneur.
    • La syntaxe COPY . . signifie copier tout le contenu du répertoire courant de l'hôte (le premier .) vers le répertoire de travail du conteneur (le second .).
  6. EXPOSE 5000 (optionnel) : Indique que le conteneur écoutera sur le port 5000.
  7. CMD ["python", "app.py"] (optionnel) : Définis la commande à exécuter lorsque le conteneur démarre.

Selon les besoins de votre application, vous pouvez ajouter ou modifier des instructions dans le Containerfile pour personnaliser l'image.

Voir la documentation officielle pour les dépôts d'images : Docker Hub

Remarque

Puisque que docker est un pionnier dans la conteneurisation,on va souvent utiliser les termes de docker comme référence.

Pour les besoins de l'exemple, nous allons utiliser un Containerfile simple comme celui ci-dessus.

Dockerfile
# Étape 1 : Utiliser une image de base Python
FROM python:3.11

# Étape 2 : Définir le répertoire de travail
WORKDIR /app

# Étape 3 : Copier le code source de l'application
COPY . .

Construction de l'image

Une fois que toutes les instructions sont définies dans le Containerfile, on pourra construire l'image à l'aide de l'interface graphique de Podman Desktop.

Remarque

Il est également possible de faire cette action (ainsi que toutes les autres actions) via la ligne de commande. Je vous invite à consulter la documentation officielle de Podman pour plus de détails : Podman CLI

first page meme

Cliquer sur le bouton "Build" en haut à droite de l'interface. Une fenêtre va s'ouvrir en vous demandant de sélectionner le Containerfile à utiliser pour la construction de l'image.

Vous devriez ensuite voir une interface similaire à celle-ci :

first page meme

Assurez vous de sélectionner le bon Containerfile, puis donner un nom a votre image dans le champ "Image Name".

Il ne vous reste qu'à build votre image (gros bouton "Build")

Après quelques instants, votre image devrait apparaitre dans la liste des images disponibles dans Podman Desktop.

first page meme

Information ❗

Remarquer ici qu'il y a une image "python:3.11" qui a été téléchargée automatiquement par Podman Desktop. C'est l'image de base que nous avons spécifiée dans le Containerfile.

Conteneurs

Qu'est-ce qu'un conteneur?

Un conteneur est une unité standardisée de logiciel qui regroupe le code de l'application et toutes ses dépendances afin que l'application puisse s'exécuter rapidement et de manière fiable d'un environnement informatique à un autre. Les conteneurs sont légers, portables et isolés, ce qui signifie qu'ils partagent le noyau du système d'exploitation hôte mais fonctionnent de manière indépendante les unes des autres.

Création et gestion des conteneurs

Une fois que vous avez une image, vous pouvez créer un conteneur à partir de cette image. Un conteneur est une instance en cours d'exécution de l'image.

Normalement, vous ne devriez pas avoir de conteneur dans votre liste au début. C'est normal, nous allons en créer un à partir de l'image que nous avons construite précédemment.

first page meme

Cliquer sur le bouton "Create", cela vous ouvrira une fenêtre de configuration du conteneur.

Truc 💡

Si vos n'avez pas "build" votre image, vous serez en mesure de créer une image à partir d'une image existante ou d'un Containerfile. Sinon, utilisez l'option "Existing image".

first page meme

Ensuite, vous allez pouvoir configurer votre conteneur.

first page meme

Assurez vous de :

  • Donner un nom a votre conteneur
  • Au besoin, configurer les ports exposés (si votre application en utilise)
  • Au besoin, configurer les volumes (si votre application en utilise)

Truc 💡

L'option de spécifier un volume est très utile en développement. Cela permet de lier un répertoire de votre machine hôte à un répertoire dans le conteneur. Ainsi, vous pouvez modifier les fichiers sur votre machine hôte et voir les changements reflétés dans le conteneur sans avoir à reconstruire l'image.

PS. Cette fonctionnalité permet de développer une application dans un conteneur de façon efficace. Cela fait en sorte qu'on n’a pas besoin d'installer toutes les dépendances sur notre machine hôte.

Il ne vous reste plus qu'à créer le conteneur en cliquant sur le bouton "Create Container".

Après quelques instants, votre conteneur devrait apparaitre dans la liste des conteneurs disponibles dans Podman Desktop.

Si vous voulez tester, vous pouvez aller dans le terminal du Container (bouton "Terminal" dans la barre en haut) et vérifier que les fichiers de votre application sont bien présents. Vous allez pouvoir également exécuter des commandes propres à votre application (comme pip dans le cas de python).

Magique, n'est-ce pas?

Podman CLI

Podman peut également être utilisé via la ligne de commande (CLI).

Veuillez vous référer à la documentation officielle de Podman CLI pour plus de détails : Podman CLI Documentation

Compose et Podman

Podman supporte également l'utilisation de fichiers Compose, similaires à Docker Compose. Cela permet de définir et de gérer des applications multiconteneurs de manière plus simple.

De façons générales, on veut avoir un conteneur par service. Par exemple, si on a une application native qui utilise une base de données, on va vouloir avoir un conteneur pour l'application native et un autre pour la base de données.

Voici un fichier Compose que j'ai utilisé dans le cadre de mon autre cour :

yaml
services:
  mongodb:
    image: mongo:latest
    container_name: mongo
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: $MONGO_ROOT_USERNAME
      MONGO_INITDB_ROOT_PASSWORD: $MONGO_ROOT_PASSWORD
    volumes:
      - mongo-data:/data/db

  mongo-express:
    container_name: mongo_express
    image: mongo-express:latest
    restart: always
    ports:
      - "8081:8081"
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: $MONGO_ROOT_USERNAME
      ME_CONFIG_MONGODB_ADMINPASSWORD: $MONGO_ROOT_PASSWORD
      ME_CONFIG_MONGODB_URL: mongodb://$MONGO_ROOT_USERNAME:$MONGO_ROOT_PASSWORD@mongodb:27017/
      ME_CONFIG_BASICAUTH_USERNAME: $ME_WEB_USERNAME
      ME_CONFIG_BASICAUTH_PASSWORD: $ME_WEB_PASSWORD
    depends_on:
      - mongodb
  express-app:
    build:
      context: .
      dockerfile: Containerfile
    container_name: express_app
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      NODE_ENV: $CURRENT_ENV
      PORT: 3000
      MONGO_DEV_URL: mongodb
    depends_on:
      - mongodb
    restart: unless-stopped

# Define named volumes
volumes:
  mongo-data:
    driver: local

Ce fichier Compose définit trois services :

  • mongodb : Un conteneur pour la base de données MongoDB.
    • Port 27017 exposé pour accéder à la base de données.
    • Variables d'environnement pour le nom d'utilisateur et le mot de passe root.
    • Volume nommé mongo-data pour persister les données de la base de données.
  • mongo-express : Un conteneur pour l'interface web de gestion de MongoDB.
    • Port 8081 exposé pour accéder à l'interface web.
    • Variables d'environnement pour la configuration de l'interface web.
    • Dépendance sur le service mongodb pour s'assurer que la base de données est démarrée avant l'interface web.
  • express-app : Un conteneur pour une application Express.js.
    • Utilisation de l'option build pour construire l'image à partir d'un Containerfile.
    • Port 3000 exposé pour accéder à l'application.
    • Volumes pour lier le code source de l'application et éviter de monter le répertoire node_modules.
    • Variables d'environnement pour la configuration de l'application.

Chaque service est configuré avec ses propres paramètres, tels que l'image à utiliser, les ports exposés, les variables d'environnement, et les volumes.

J'ai également défini des variables d'environnement dans les conteneurs pour gérer les configurations sensibles comme les noms d'utilisateur et les mots de passe.

Vous pourrez remarquer que dans mon container express-app, j'ai utilisé l'option build pour spécifier le contexte de construction et le Containerfile à utiliser. Cela permet de construire l'image directement à partir du fichier Compose.

Pour démarrer, les services définis dans le fichier Compose, vous pouvez utiliser la commande suivante dans le terminal :

bash
podman compose up -d

Il est également possible de le faire avec l'application desktop.

Pour arrêter et supprimer les services, vous pouvez utiliser la commande suivante :

bash
podman compose down -v

Le -v est une option qui permet de supprimer les volumes associés aux conteneurs.

Également possible de le faire avec l'application desktop.

Utilisation pour votre projet

Si vous le souhaitez, je vous recommande d'utiliser la conteneurisation afin d'exécuter votre projet. Cela vous permettra de tester l'outil et de limiter l'installation de dépendances sur votre machine hôte.

Truc 💡

Au besoin, nous pourrons regarder ensemble votre Containerfile et/ou votre fichier Compose durant le cours afin de s'assurer de leur bon fonctionnement.

420-6N1-DM - Développement d’applications natives IV