Exécuter des Conteneurs avec Podman sur RHEL

Red Hat Enterprise LinuxBeginner
Pratiquer maintenant

Introduction

Dans ce laboratoire, vous apprendrez à déployer une application web multi-tiers en utilisant Podman sur Red Hat Enterprise Linux (RHEL). Vous construirez une solution complète en déployant un conteneur de base de données MariaDB en tant que backend et un conteneur de serveur web Apache en tant que frontend. Cette expérience pratique vous guidera à travers les étapes essentielles du déploiement d'applications conteneurisées, de la configuration initiale à la mise à disposition publique du service.

Vous commencerez par exécuter un conteneur MariaDB et le configurerez au démarrage avec des variables d'environnement. Ensuite, vous configurerez un stockage persistant pour assurer la durabilité des données de la base de données et créerez un réseau personnalisé pour la communication entre les conteneurs. Vous déploieriez ensuite le serveur web Apache, exposerez son port pour tester la connectivité et, enfin, apprendrez à gérer le conteneur en tant que service systemd pour une opération robuste et automatisée.

Exécuter un Conteneur de Base de Données MariaDB avec des Variables d'Environnement

Dans cette étape, vous apprendrez à exécuter une application conteneurisée et à la configurer au démarrage en utilisant des variables d'environnement. C'est une compétence fondamentale dans la gestion des conteneurs, permettant des déploiements flexibles et sécurisés. Nous utiliserons l'image officielle MariaDB comme exemple, car elle nécessite plusieurs paramètres de configuration pour initialiser une base de données.

Tout d'abord, assurez-vous d'être dans le répertoire de travail correct. Tout le travail pour ce laboratoire sera effectué dans le répertoire ~/project.

cd ~/project

Avant d'exécuter un conteneur, il est de bonne pratique de tirer explicitement l'image du registre. Cela garantit que vous disposez de la bonne version localement. Nous utiliserons l'image mariadb:10.6 pour ce laboratoire afin d'assurer la cohérence.

podman pull mariadb:10.6

Sélectionnez l'image mariadb:10.6 du registre Docker.

Vous devriez voir une sortie indiquant que l'image est en cours de téléchargement et d'extraction.

10.6: Pulling from library/mariadb
...
Status: Downloaded newer image for mariadb:10.6
docker.io/library/mariadb:10.6

Maintenant, vous pouvez exécuter le conteneur MariaDB. La commande podman run crée et démarre un nouveau conteneur. Nous utiliserons plusieurs options :

  • -d : Exécute le conteneur en mode détaché (en arrière-plan).
  • --name mariadb_server : Attribue un nom mémorable à notre conteneur.
  • -e VARIABLE=value : Définit une variable d'environnement à l'intérieur du conteneur. L'image MariaDB les utilise pour configurer la base de données lors du premier lancement.

Exécutez la commande suivante pour démarrer votre conteneur MariaDB. Nous définissons le mot de passe root et créons également une nouvelle base de données nommée webappdb avec un utilisateur dédié webappuser.

podman run -d \
  --name mariadb_server \
  -e MARIADB_ROOT_PASSWORD=supersecret \
  -e MARIADB_DATABASE=webappdb \
  -e MARIADB_USER=webappuser \
  -e MARIADB_PASSWORD=userpass \
  mariadb:10.6

La commande affichera un long ID de conteneur, ce qui confirme que le conteneur a été créé.

a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2

Pour vérifier que le conteneur est en cours d'exécution, utilisez la commande podman ps.

podman ps

Vous devriez voir mariadb_server dans la liste des conteneurs en cours d'exécution.

CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS      NAMES
a1b2c3d4e5f6   mariadb:10.6   "docker-entrypoint.s…"   15 seconds ago   Up 14 seconds   3306/tcp   mariadb_server

Enfin, vérifions les journaux du conteneur pour nous assurer que la base de données s'est initialisée correctement en utilisant les variables d'environnement que nous avons fournies.

podman logs mariadb_server

Faites défiler les journaux. Vous recherchez une ligne qui indique que le serveur est prêt pour les connexions, ce qui confirme un démarrage réussi. La sortie sera longue, mais un message de réussite clé vers la fin ressemble à ceci :

...
2024-05-20 10:30:00+00:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/
...
2024-05-20 10:30:15+00:00 [Note] mariadbd: ready for connections.
Version: '10.6.x-MariaDB-1:10.6.x+maria~ubu2004'  socket: '/run/mysqld/mysqld.sock'  port: 3306  mariadb.org binary distribution

Vous avez réussi à lancer et à configurer un conteneur MariaDB en utilisant des variables d'environnement.

Configurer le Stockage Persistant pour le Conteneur MariaDB

Dans cette étape, vous apprendrez à configurer le stockage persistant pour un conteneur. Par défaut, toutes les données créées à l'intérieur d'un conteneur sont stockées dans une couche accessible en écriture qui est liée au cycle de vie du conteneur. Si vous supprimez le conteneur, toutes ces données sont perdues. Pour les applications avec état (stateful applications) comme les bases de données, ce n'est pas idéal. Pour résoudre ce problème, nous utilisons les volumes Podman ou les montages de liaison (bind mounts) pour stocker les données sur le système de fichiers de l'hôte, indépendamment du conteneur.

Tout d'abord, nous devons supprimer le conteneur que nous avons créé à l'étape précédente, car nous allons le relancer avec une nouvelle configuration de stockage.

Arrêtez le conteneur mariadb_server en cours d'exécution :

podman stop mariadb_server

Vous verrez le nom du conteneur en sortie, confirmant que la commande a été reçue.

mariadb_server

Maintenant, supprimez le conteneur arrêté :

podman rm mariadb_server

Encore une fois, le nom du conteneur sera renvoyé.

mariadb_server

Ensuite, créez un répertoire sur votre machine hôte dans le répertoire ~/project. Ce répertoire contiendra les fichiers de la base de données MariaDB.

mkdir ~/project/mariadb_data

Lorsque vous utilisez Podman en mode sans root (rootless mode), nous devons définir les permissions correctes pour le répertoire monté. Le conteneur MariaDB s'exécute en tant qu'utilisateur spécifique (UID 999), nous devons donc nous assurer que le répertoire est accessible. Nous utiliserons l'option --userns=keep-id et définirons les permissions appropriées :

chmod 755 ~/project/mariadb_data

Maintenant, exécutez à nouveau le conteneur MariaDB. Cette commande est similaire à celle de l'étape précédente, mais avec l'ajout de l'option -v et --userns=keep-id pour gérer correctement le mappage de l'espace de noms utilisateur. L'option -v monte le répertoire ~/project/mariadb_data de votre hôte dans le répertoire /var/lib/mysql à l'intérieur du conteneur, c'est là que MariaDB stocke ses données. Nous utilisons $(pwd)/mariadb_data pour fournir le chemin absolu requis à la commande podman.

podman run -d \
  --name mariadb_server \
  --userns=keep-id \
  -e MARIADB_ROOT_PASSWORD=supersecret \
  -e MARIADB_DATABASE=webappdb \
  -e MARIADB_USER=webappuser \
  -e MARIADB_PASSWORD=userpass \
  -v $(pwd)/mariadb_data:/var/lib/mysql:Z \
  mariadb:10.6

Le suffixe :Z sur le montage de volume indique à Podman de ré-étiqueter le contenu avec une étiquette privée non partagée, ce qui est important pour la compatibilité SELinux.

Après le démarrage du conteneur, vous pouvez vérifier que les données sont stockées sur votre machine hôte. Listez le contenu du répertoire ~/project/mariadb_data.

ls -l ~/project/mariadb_data

Parce que le moteur de base de données du conteneur s'est initialisé, vous verrez plusieurs fichiers et répertoires créés à l'intérieur de ~/project/mariadb_data. Cela confirme que vos données sont maintenant persistantes. Même si vous supprimez le conteneur, ces données resteront.

total 110632
-rw-rw---- 1 labex labex    16384 May 20 10:45 aria_log.00000001
-rw-rw---- 1 labex labex       52 May 20 10:45 aria_log_control
-rw-rw---- 1 labex labex      983 May 20 10:45 ib_buffer_pool
-rw-rw---- 1 labex labex 12582912 May 20 10:45 ibdata1
-rw-rw---- 1 labex labex 50331648 May 20 10:45 ib_logfile0
-rw-rw---- 1 labex labex 50331648 May 20 10:45 ib_logfile1
drwx------ 2 labex labex     4096 May 20 10:45 mysql
drwx------ 2 labex labex     4096 May 20 10:45 performance_schema
drwx------ 2 labex labex     4096 May 20 10:45 sys
drwx------ 2 labex labex     4096 May 20 10:45 webappdb

Vous avez configuré avec succès votre conteneur MariaDB pour utiliser le stockage persistant, garantissant que les données de votre base de données survivront aux redémarrages et aux suppressions de conteneurs.

Créer un Réseau Personnalisé et Déployer un Serveur Web Apache

Dans cette étape, vous allez créer un réseau personnalisé pour vos conteneurs et déployer un serveur web Apache. Bien que Podman fournisse un réseau par défaut, l'utilisation de réseaux personnalisés est une bonne pratique. Ils offrent une meilleure isolation et, surtout, permettent la résolution DNS automatique entre les conteneurs. Cela permet aux conteneurs de communiquer entre eux en utilisant leurs noms, ce qui est plus fiable que d'utiliser des adresses IP qui peuvent changer.

Tout d'abord, créons un réseau pont personnalisé pour notre application. Nous l'appellerons webapp-network.

podman network create webapp-network

La commande affichera le nom du réseau nouvellement créé.

webapp-network

Vous pouvez lister tous les réseaux Podman pour confirmer que le vôtre a été créé avec succès.

podman network ls

Vous devriez voir webapp-network dans la liste, ainsi que les réseaux par défaut.

NETWORK ID     NAME               DRIVER    SCOPE
...
f1e2d3c4b5a6   webapp-network     bridge    local
...

Ensuite, nous devons recréer notre conteneur mariadb_server sur ce nouveau réseau. En raison de la configuration du backend réseau dans cet environnement, nous ne pouvons pas connecter un conteneur existant à un nouveau réseau. Au lieu de cela, nous allons arrêter et recréer le conteneur avec la nouvelle configuration réseau.

Arrêtez le conteneur mariadb_server en cours d'exécution :

podman stop mariadb_server

Supprimez le conteneur arrêté :

podman rm mariadb_server

Maintenant, recréez le conteneur MariaDB avec le nouveau réseau. Cette commande est similaire à celle de l'étape précédente, mais avec l'ajout de l'option --network webapp-network :

podman run -d \
  --name mariadb_server \
  --network webapp-network \
  --userns=keep-id \
  -e MARIADB_ROOT_PASSWORD=supersecret \
  -e MARIADB_DATABASE=webappdb \
  -e MARIADB_USER=webappuser \
  -e MARIADB_PASSWORD=userpass \
  -v $(pwd)/mariadb_data:/var/lib/mysql:Z \
  mariadb:10.6

Maintenant, déployons notre serveur web. Nous utiliserons l'image officielle Apache httpd. Tout d'abord, créez un répertoire sur l'hôte pour stocker les fichiers de votre site web.

mkdir ~/project/webapp_content

Créez un simple fichier index.html dans ce nouveau répertoire. Ce sera la page d'accueil de notre application web.

echo "<h1>Welcome to My Web App</h1>" > ~/project/webapp_content/index.html

Définissez les permissions correctes pour le répertoire de contenu webapp afin de garantir que le conteneur Apache peut accéder aux fichiers :

chmod 755 ~/project/webapp_content

Maintenant, exécutez le conteneur Apache httpd. Nous allons l'attacher à notre webapp-network et monter le répertoire webapp_content en tant que volume. Cela garantit que le serveur web peut servir le fichier index.html que nous venons de créer.

podman run -d \
  --name web_server \
  --network webapp-network \
  -v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
  httpd:2.4

Décomposons les options :

  • --network webapp-network : Connecte le nouveau conteneur à notre réseau personnalisé.
  • -v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z : Cela monte notre répertoire local webapp_content dans le conteneur à /usr/local/apache2/htdocs/, qui est le répertoire par défaut à partir duquel Apache sert les fichiers. Le suffixe :Z indique à Podman de ré-étiqueter le contenu avec une étiquette privée non partagée pour la compatibilité SELinux.

Vérifiez que les deux conteneurs sont en cours d'exécution.

podman ps

Vous devriez maintenant voir à la fois mariadb_server et web_server dans la liste des conteneurs en cours d'exécution.

CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS         PORTS       NAMES
6a3f46c0ab3a  docker.io/library/mariadb:10.6  mariadbd          29 seconds ago  Up 29 seconds  3306/tcp    mariadb_server
da5d52ce9c41  docker.io/library/httpd:2.4     httpd-foreground  7 seconds ago   Up 7 seconds   80/tcp      web_server

Les deux conteneurs sont maintenant sur le même réseau personnalisé et peuvent communiquer entre eux par nom.

Exposer le Port du Serveur Web et Tester la Connectivité

Dans cette étape, vous apprendrez à exposer le port d'un conteneur à la machine hôte, rendant le service accessible de l'extérieur du réseau isolé du conteneur. Notre serveur web Apache est en cours d'exécution, mais nous ne pouvons pas encore y accéder depuis le navigateur ou la ligne de commande de notre hôte. Nous allons corriger cela en publiant le port du conteneur.

Les mappages de ports sont définis lorsqu'un conteneur est créé. Par conséquent, nous devons d'abord arrêter et supprimer le conteneur web_server que nous avons créé à l'étape précédente. Ne vous inquiétez pas du contenu du site web ; il est en sécurité dans le répertoire ~/project/webapp_content sur notre hôte car nous avons utilisé un montage de liaison (bind mount).

Tout d'abord, arrêtez le conteneur :

podman stop web_server
web_server

Ensuite, supprimez le conteneur arrêté :

podman rm web_server
web_server

Maintenant, nous allons exécuter à nouveau le conteneur web_server, mais cette fois, nous ajouterons l'option -p (ou --publish) pour mapper un port de l'hôte à un port du conteneur. Nous allons mapper le port 8080 sur l'hôte au port 80 (le port HTTP par défaut) à l'intérieur du conteneur.

podman run -d \
  --name web_server \
  --network webapp-network \
  -v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
  -p 8080:80 \
  httpd:2.4

La nouvelle option -p 8080:80 indique à Podman de transférer tout le trafic du port 8080 sur l'hôte vers le port 80 à l'intérieur du conteneur web_server.

Vérifions que le conteneur est en cours d'exécution et que le port est correctement mappé en utilisant podman ps.

podman ps

Remarquez la colonne PORTS pour le conteneur web_server. Elle affiche maintenant le mappage de 0.0.0.0:8080 à 80/tcp, indiquant que le port est correctement exposé.

CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                  NAMES
c5d4e3f2a1b6   httpd:2.4      "httpd-foreground"       10 seconds ago   Up 9 seconds    0.0.0.0:8080->80/tcp   web_server
a1b2c3d4e5f6   mariadb:10.6   "docker-entrypoint.s…"   25 minutes ago   Up 25 minutes   3306/tcp               mariadb_server

Enfin, testons la connectivité depuis notre machine hôte en utilisant la commande curl. Cela envoie une requête HTTP à localhost sur le port 8080.

curl http://localhost:8080

Vous devriez voir le contenu HTML de votre fichier index.html en sortie, confirmant que votre serveur web est maintenant accessible depuis l'hôte.

<h1>Welcome to My Web App</h1>

Vous avez réussi à exposer votre serveur web conteneurisé à la machine hôte, une étape cruciale pour rendre les applications disponibles aux utilisateurs.

Gérer le Conteneur du Serveur Web en tant que Service systemd

Dans cette dernière étape, vous apprendrez à configurer un conteneur pour qu'il démarre automatiquement, garantissant ainsi que votre service est résistant aux pannes ou aux redémarrages du système. Sur un système Red Hat Enterprise Linux standard, systemd est l'outil principal pour gérer les services. Cependant, l'environnement Podman dans ce laboratoire n'utilise pas systemd pour gérer directement les conteneurs.

Au lieu de cela, nous obtiendrons le même résultat — les redémarrages automatiques du service — en utilisant les politiques de redémarrage intégrées de Podman. C'est la méthode standard, native des conteneurs, pour garantir qu'un conteneur est automatiquement démarré par le démon Podman. Nous configurerons notre web_server pour qu'il redémarre toujours s'il s'arrête pour une raison quelconque.

Tout d'abord, nous devons supprimer le conteneur existant, car les politiques de redémarrage ne peuvent être appliquées que lors de la création d'un conteneur.

Arrêtez le conteneur web_server :

podman stop web_server
web_server

Et maintenant, supprimez-le :

podman rm web_server
web_server

Ensuite, recréez le conteneur web_server avec la même configuration qu'avant, mais ajoutez l'option --restart always. Cette option indique au démon Podman de surveiller le conteneur et de le redémarrer s'il s'arrête.

podman run -d \
  --name web_server \
  --network webapp-network \
  -v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
  -p 8080:80 \
  --restart always \
  httpd:2.4

Le conteneur démarrera comme d'habitude. Pour confirmer que la politique de redémarrage est active, vous pouvez inspecter la configuration du conteneur.

podman inspect web_server --format '{{.HostConfig.RestartPolicy.Name}}'

La commande devrait renvoyer always, confirmant que la politique est définie.

always

Maintenant, démontrons comment la politique de redémarrage fonctionne en redémarrant manuellement le conteneur pour simuler ce qui se passerait après un redémarrage du système ou une panne du conteneur.

Tout d'abord, vérifions la configuration actuelle de la politique de redémarrage :

podman inspect web_server --format '{{.HostConfig.RestartPolicy.Name}}'

Cela devrait afficher always, confirmant que notre politique de redémarrage est configurée.

always

Maintenant, testons le redémarrage manuel pour simuler la récupération après une panne :

podman start web_server
web_server

Vérifiez que le conteneur est en cours d'exécution :

podman ps

Vous devriez voir les deux conteneurs en cours d'exécution avec la politique de redémarrage en place :

CONTAINER ID   IMAGE          COMMAND                  CREATED              STATUS              PORTS                  NAMES
e7f6g5h4i3j2   httpd:2.4      "httpd-foreground"       About a minute ago   Up 5 seconds        0.0.0.0:8080->80/tcp   web_server
a1b2c3d4e5f6   mariadb:10.6   "docker-entrypoint.s…"   About an hour ago    Up About an hour    3306/tcp               mariadb_server

Enfin, confirmez que le service est accessible :

curl http://localhost:8080
<h1>Welcome to My Web App</h1>

Comprendre les politiques de redémarrage :

La politique --restart always que vous avez configurée garantit que :

  • Le conteneur redémarrera automatiquement s'il s'arrête de manière inattendue
  • Le conteneur démarrera automatiquement lorsque le service Podman démarrera (par exemple, après un redémarrage du système)
  • Cela offre une résilience pour les déploiements en production

Remarque : Dans certains environnements de laboratoire, le comportement de redémarrage automatique peut varier en fonction de la configuration de Podman et de l'exécution ou non du service système Podman. L'objectif d'apprentissage clé est de comprendre comment configurer les politiques de redémarrage pour les déploiements en production.

Vous avez réussi à configurer votre conteneur pour qu'il soit géré comme un service, garantissant ainsi qu'il reste disponible automatiquement. Cela complète la gestion du cycle de vie de base d'une application conteneurisée.

Résumé

Dans ce laboratoire, vous avez appris le processus fondamental de déploiement d'une application web multi-conteneurs sur RHEL en utilisant Podman. Vous avez commencé par exécuter un conteneur de base de données MariaDB, en configurant son état initial — y compris le mot de passe root, une nouvelle base de données et un utilisateur dédié — en passant des variables d'environnement au moment de l'exécution. Vous avez ensuite configuré le stockage persistant pour le conteneur de base de données, garantissant ainsi que les données critiques sont conservées lors des redémarrages du conteneur.

Pour compléter la pile d'applications, vous avez créé un réseau personnalisé pour permettre une communication sécurisée et isolée entre les conteneurs. Vous avez déployé un conteneur de serveur web Apache sur ce réseau et exposé son port pour permettre l'accès des utilisateurs externes. Enfin, vous avez intégré le conteneur du serveur web avec systemd, en le gérant comme un service système pour garantir qu'il démarre automatiquement au démarrage et fonctionne de manière fiable, démontrant ainsi un modèle de déploiement prêt pour la production.