Podman, Quadlet et WordPress

Bonjour à tous,

Le 1er février 2023 sortait la version 4.4 de Podman. Podman est un moteur de conteneur open source, développé par Red Hat, qui offre une gestion avancée des conteneurs et des images sur des systèmes Linux. En rivalité avec Docker, il permet aux utilisateurs de créer, exécuter et gérer des environnements de conteneurisation de manière efficace et sécurisée.

Cette version 4.4 comprenait notamment l’introduction de Quadlet, un nouveau générateur de service Systemd pour écrire et maintenir facilement des services pour les conteneurs et pods créé par Podman. Cela peut sembler anecdotique dit comme cela mais il s’agit d’une véritable révolution dans la façon de générer et d’administrer les services pour les conteneurs et pods.

Le projet Spirio est l’occasion pour moi d’approfondir mes connaissances de l’écosystème de Podman. Cet article est le premier d’une petite série afin de vous partager mes découvertes à travers la configuration de mysql et de WordPress avec des Quadlet.

Présentation

Fonctionnement des Quadlet

La syntaxe des fichiers Quadlet est très proche de celles des fichiers Unit de Systemd. Un exemple ci-dessous:

[Unit]
Description=A minimal container

[Container|Volume|Network]
Image=centos

[Service]
Restart=always

[Install]
WantedBy=default.target

Les directives qui peuvent être dans ce fichier se trouvent dans le manuel – man [podman-systemd.unit][https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html]. On retrouve la plupart des directives des fichiers docker-compose tel que volumes, hostname, networks, image etc.

Les fichiers Quadlet peuvent être disposés dans différents répertoires :

  • /etc/containers/systemd/
  • /etc/containers/systemd/user (Pour l’execution de pod en mode rootless)
  • ~/.config/containers/systemd/ (Pour l’execution de pod par l’utilisateur courant)
    Personnellement, je préfère les placer dans le répertoire /etc/containers/systemd/ afin d’avoir tous les fichiers Quadlet au même endroit.

Installation de Podman

Introduit dans la version 4.4 qui date de février 2023, l’exhaustivité ‘du format Quadlet ne fut pas complète même si elle s’améliore au fil des versions. On observera notamment le support de uidmap/gidmap en version 4.7 et Entrypoint /StopTimeout en version 5.0 (sortie il y a quelques jours).

De ce fait, il est nécessaire d’avoir une version assez récente de Podman afin de pouvoir exploiter pleinement la puissance des Quadlets. La version disponible sur Debian 12 est la version 4.3.1 et nous allons installer la version de testing afin de pouvoir utiliser la version 5.0.

echo 'APT::Default-Release "stable";'| sudo tee /etc/apt/apt.conf.d/99defaultrelease

echo "deb http://deb.debian.org/debian/ trixie main non-free-firmware non-free" | sudo tee  /etc/apt/sources.list.d/testing.list
echo "deb http://security.debian.org/debian-security trixie-security main non-free-firmware non-free" | sudo tee -a  /etc/apt/sources.list.d/testing.list
echo "deb http://deb.debian.org/debian/ trixie-updates main non-free-firmware non-free" | sudo tee -a  /etc/apt/sources.list.d/testing.list

sudo apt update
sudo apt install podman/testing

Installation de Mysql

Création du volume

Afin de savoir quels sont les volumes nécessaires à Mysql pour fonctionner, on peut utiliser la commande podman inspect pour en savoir plus.

podman inspect --format {{.Config.Volumes}} mysql:latest
map[/var/lib/mysql:{}]

La commande nous indique qu’il y a un volume avec comme chemin /var/lib/mysql. Nous allons créer un répertoire /srv/wp-mysql afin de le lier à ce répertoire. L’objectif de cet article est de vous familiariser avec Quadlet, nous allons créer manuellement un volume au format Quadlet en spécifiant ce chemin.

mkdir /srv/wp-mysql

# cat /etc/containers/systemd/wp-mysql.volume
[Unit]
Description=Mysql Database Container Volume

[Volume]
Type=bind
Device=/srv/wp-mysql

[Install]
WantedBy=default.target

Afin que ce volume s’exécute au démarrage du serveur, il faut ajouter le [Install] WantedBy=default.target.

Pour information, il est possible de ne pas créer de volume dédié, car Podman est en capacité de les créer à la volée. Il est également possible de lier directement les deux répertoires sans avoir à utiliser de de volume.

Création du réseau

Nous allons créer un réseau spécifiquement dédié à la base de données Mysql et à WordPress. Cela permet d’améliorer la sécurité en les isolant des réseaux des conteneurs.

# cat /etc/containers/systemd/wp.network
[Unit]
Description=Wordpress Container Network

[Network]

[Install]
WantedBy=default.target

Création des secrets

Depuis la version 2.0 de Podman sortie en avril 2021, Podman permet de mettre à disposition des conteneurs des secrets de façon sécurisée. Dans le cadre de l’installation de WordPress, nous avons besoin de deux secrets. Le premier est le mot de passe du compte root de Mysql et le second est le mot de passe d’accès à la base de données de WordPress.

Tous les fichiers de configuration de WordPress et de sa base de données seront conservés dans le répertoire /etc/wordpress. Nous allons commencer par générer les secrets.

sudo mkdir /etc/wordpress
openssl rand -base64 32|tee /etc/wordpress/wp-mysql_MYSQL_ROOT_PASSWORD
openssl rand -base64 32|tee /etc/wordpress/wp-mysql_MYSQL_PASSWORD

Une fois générés, nous allons les charger avec Podman afin de pouvoir les utiliser dans les fichiers Quadlets.

podman secret create wp-mysql_MYSQL_ROOT_PASSWORD /etc/wordpress/wp-mysql_MYSQL_ROOT_PASSWORD
podman secret create wp-mysql_MYSQL_PASSWORD /etc/wordpress/wp-mysql_MYSQL_PASSWORD

Création du Quadlet

# cat /etc/containers/systemd/wp-mysql.container
# wp-mysql.container
[Container]
ContainerName=wp-mysql
Image=docker.io/library/mysql:latest

Environment=MYSQL_ROOT_PASSWORD_FILE=/run/secrets/wp-mysql_MYSQL_ROOT_PASSWORD MYSQL_DATABASE=wordpress MYSQL_USER=wordpress MYSQL_PASSWORD_FILE=/run/secrets/wp-mysql_MYSQL_PASSWORD
Secret=wp-mysql_MYSQL_ROOT_PASSWORD wp-mysql_MYSQL_PASSWORD

Exec='--default_authentication_plugin=caching_sha2_password' '--character-set-server=utf8mb4' '--collation-server=utf8mb4_unicode_ci'
Network=wp.network

Volume=wp-mysql.volume:/var/lib/mysql

[Service]
Restart=always

[Install]
WantedBy=default.target

Quelques explications :

  • Image=docker.io/library/mysql:latest
    Le nom absolu de l’image avec spécification du registre permet d’éviter de permettre un démarrage sans manipulation de l’administrateur.
  • Environment=MYSQL_ROOT_PASSWORD_FILE=/run/secrets/wordpress-mysql_MYSQL_ROOT_PASSWORD MYSQL_DATABASE=wordpress MYSQL_USER=wordpress MYSQL_PASSWORD_FILE=/run/secrets/wp-mysql_MYSQL_PASSWORD
    Définition des variables d’environnement pour définir les mots de passe ROOT et pour l’utilisateur wordpress ainsi que la création d’un utilisateur et d’une base de données wordpress
  • Secret=wp-mysql_MYSQL_ROOT_PASSWORD wp-mysql_MYSQL_PASSWORD
    Chargement des secrets
  • Exec=’–default_authentication_plugin=caching_sha2_password’ ‘–character-set-server=utf8mb4’ ‘–collation-server=utf8mb4_unicode_ci’
    Paramètre de démarrage de Mysql
  • Network=wp.network
    Utilisation du réseau que nous avons créé préalablement.
  • Volume=wp-mysql.volume:/var/lib/mysql
    Utilisation du volume que nous avons créé préalablement.
  • Restart=always
    Redémarrage en cas d’arrêt du service.
  • WanteBy=default.target
    Démarrage du service lors du démarrage du système.

Installation de WordPress

Création du volume

Afin de savoir quels sont les volumes nécessaires à WordPress pour fonctionner, on peut utiliser la commande podman inspect pour en savoir plus.

podman inspect --format {{.Config.Volumes}} wordpress:latest
map[/var/www/html:{}]

La commande nous indique qu’il y a un volume avec comme chemin /var/www/html. Nous allons créer un répertoire /srv/wp-wordpress afin de le lier à ce répertoire. L’objectif de cet article est de vous familiarisez avec Quadlet, nous allons créer manuellement un volume au format Quadlet en spécifiant ce chemin.

mkdir /srv/wp-wordpress

# cat /etc/containers/systemd/wp-wordpress.volume
[Unit]
Description=Wordpress Container Volume

[Volume]
Type=bind
Device=/srv/wp-wordpress

[Install]
WantedBy=default.target

Création du Quadlet

# cat /etc/containers/systemd/wp-wordpress.container
# wp-wordpress.container
[Unit]
Requires=wp-mysql.service

[Container]
ContainerName=wp-wordpress
Image=docker.io/library/wordpress:latest

Environment=WORDPRESS_DB_HOST=wp-mysql.dns.podman:3306 WORDPRESS_DB_NAME=wordpress WORDPRESS_DB_USER=wordpress WORDPRESS_DB_PASSWORD_FILE=/run/secrets/wp-mysql_MYSQL_PASSWORD WP_HOME=https://spirio.fr WP_SITEURL=https://spirio.fr
Secret=wp-mysql_MYSQL_PASSWORD

Network=wp.network
IP=10.89.1.3
PublishPort=127.0.0.1:8000:2000

Volume=wp-wordpress.volume:/var/www/html/

[Service]
Restart=always

[Install]
WantedBy=default.target

Quelques explications :

  • Requires=wp-mysql.service
    Cela permet d’indiquer que le service de WordPress nécessite que le service wp-mysql soit fonctionnel pour démarrer. Si ce n’est pas le cas, le service wp-mysql sera démarré.
  • ContainerName=wp-wordpress
    Le nom du conteneur dans Podman
  • Image=docker.io/library/wordpress:latest
    Le nom absolu de l’image avec spécification du registre permet d’éviter de permettre un démarrage sans manipulation de l’administrateur.
  • Environment=WORDPRESS_DB_HOST=wordpress-mysql.dns.podman:3306 WORDPRESS_DB_NAME=wordpress WORDPRESS_DB_USER=wordpress WORDPRESS_DB_PASSWORD_FILE=/run/secrets/wordpress-mysql_MYSQL_PASSWORD WP_HOME=https://spirio.fr WP_SITEURL=https://spirio.fr
    Les variables d’environnement nécessaire au fonctionnement de WordPress. L’identification de la base de données est réalisée via résolution DNS. Les réseaux créés par Podman intègre un DNS local qui permet de résoudre sur les machines connectées les noms des conteneurs.
  • Secret=wp-mysql_MYSQL_PASSWORD
    Chargement des secrets
  • Network=wordpress.network
    Utilisation du réseau que nous avons créé préalablement.
  • IP=10.89.1.3
    La spécification d’une adresse IP permet de mettre en place des règles réseaux spécifiques à ce conteneur et de l’isoler.
  • PublishPort=127.0.0.1:8080:80
    Indique que le port 80 du conteneur doit être accessible via le port 127.0.0.1:8080 de l’hôte. Cela permettra de disposer un reverse proxy sur le port 80/443 et rediriger les flux vers ce localhost.
  • Volume=/srv/wordpress/html:/var/www/html/
    Chargement du volume qui contient les fichiers de WordPress.
  • Restart=always
    Redémarrage du service en cas d’échec
  • WantedBy=default.target
    Démarrage du service lors du démarrage du système.

Orchestration

La configuration des Quadlets est terminée. Pour vérifier qu’il n’y a pas d’erreur, nous pouvons utiliser la commande /usr/lib/systemd/system-generator/podman-generator –dryrun.

/usr/lib/systemd/system-generator/podman-generator --dryrun

Tout semble correcte, il est désormais nécessaire de recharger la configuration de Systemd et de démarrer les services.

systemctl daemon-reload

systemctl start wp-network
systemctl start wp-mysql-volume
systemctl start wp-wordpress-volume

systemctl start wp-wordpress
systemctl status wp-wordpress

Pour aller plus loin

Quelques pistes pour ceux qui veulent aller plus loin :

  • Isoler les conteneurs des autres conteneurs ;
  • Créer un utilisateur WordPress et faire fonctionner WordPress et sa base de données en mode rootless ;
  • Spécifier l’utilisateur sous lequel les processus à l’intérieur du conteneur doivent s’exécuter. Cette option est utile pour améliorer la sécurité en limitant les privilèges du conteneur.

Ces pistes seront explorées dans un second article ultérieurement.

Conclusion

Comme vous avez pu le voir au cours de cet article, le format Quadlet améliore la lisibilité de la configuration des conteneurs ainsi que la génération de services Systemd. J’espère que vous avez trouvé cet article utile et qu’il vous a donné envie d’essayer de gérer vos conteneurs avec Podman.

Le format Quadlet est encore en pleine mouvance, il manque un certains nombres de paramètre natif de Podman, notamment les Entrypoint mais cela arrive.


Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *