Comment exécuter des conteneurs Podman sous Systemd avec Quadlet
Quadlet est un outil gratuit et open source écrit en C qui nous permet de créer et d’exécuter des conteneurs Podman sous Systemd. L’outil nous permet de déclarer les conteneurs, les volumes, les réseaux et leurs relations, à l’aide d’unités Systemd dédiées.
Dans ce tutoriel, nous apprenons à utiliser Quadlet pour créer des conteneurs, des réseaux et des volumes Podman, ainsi qu’à créer des piles multi-conteneurs.
Dans ce tutoriel, vous allez apprendre :
- Comment créer des conteneurs, des volumes et des réseaux avec les unités Systemd correspondantes
- Comment créer des piles multi-conteneurs à l’aide de Quadlet
Un exemple de base : la création d’un conteneur MariaDB
Dans ce premier exemple de base, nous définissons une unité pour un serveur de base de données MariaDB. Voici à quoi cela ressemble :
[Unit]
Description=MariaDB container
[Container]
Image=docker.io/mariadb:latest
Environment=MYSQL_ROOT_PASSWORD=rootpassword
Environment=MYSQL_USER=testuser
Environment=MYSQL_PASSWORD=testpassword
Environment=MYSQL_DATABASE=testdb
[Install]
WantedBy=multi-user.targetAvec ces quelques lignes, nous avons défini un conteneur basé sur la dernière image officielle de MariaDB, disponible sur Dockerhub. Comme vous pouvez le voir, un « .container » est un type dédié d’unité Systemd. Ce qui est unique à ce type d’unité, c’est la section « Container », dans laquelle nous pouvons spécifier des options qui sont les équivalents de celles que nous pouvons passer à la ligne de commande de Podman. La seule option requise dans la section « Conteneur » est Image, pour spécifier l’image de base du conteneur.
Si nous voulons que le conteneur s’exécute en tant que root, nous enregistrons le fichier dans le répertoire /etc/containers/systemd ; Pour l’exécuter en tant que notre propre utilisateur non privilégié, à la place, nous l’enregistrons sous ~/.config/containers/systemd. Dans cet exemple, nous allons utiliser cette dernière approche et enregistrer notre unité « .container " sous le nom ~/.config/containers/systemd/mariadb-service.container. Pour permettre à systemd de générer un service basé sur l’unité de conteneur, nous exécutons la commande suivante :
systemctl --user daemon-reloadAprès avoir exécuté la commande, nous pouvons jeter un coup d’œil au service généré en exécutant :
systemctl --user cat mariadb-servicePour démarrer le conteneur, comme n’importe quel autre service, nous pouvons exécuter :
systemctl --user start mariadb-serviceLa première fois que nous le lançons, le service peut prendre un certain temps à démarrer, si l’image de base du conteneur n’existe pas sur notre système. Nous pouvons utiliser la ligne de commande podman pour vérifier l’état du conteneur :
podman psLa commande renvoie la sortie suivante, qui confirme que le conteneur est opérationnel :
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
151226b10a1c docker.io/library/mariadb:latest mariadbd 59 seconds ago Up About a minute systemd-mariadb-serviceComme vous l’avez peut-être remarqué, par défaut, le conteneur est nommé d’après le fichier d’unité « .container " plus le préfixe « systemd- " (« systemd-mariadb-service », dans ce cas). Pour attribuer explicitement un nom au conteneur, nous pouvons toutefois le passer en tant que valeur de l’option ContainerName à l’intérieur de la section « [Container] ».
Création d’une unité « volume »
Nous utilisons des volumes pour conserver les données des conteneurs. Dans ce cas, nous voulons que les données de notre base de données persistent même si nous abandonnons le conteneur systemd-mariadb-service. Nous définissons un volume nommé dans l’unité « .volume » correspondante. Dans l’exemple ci-dessous, nous fournissons simplement une description du volume. Des options spécifiques au volume peuvent être spécifiées sous la strophe [Volume] :
[Unit]
Description=MariaDB Volume
[Volume]
Nous enregistrons l’unité sous le nom ~/.config/containers/systemd/mariadb-volume.volume. Pour indiquer au conteneur MariaDB d’utiliser le volume, nous utilisons l’option Volume à l’intérieur de la section [Container] de l’unité « .container », et nous mappons le volume au répertoire /var/lib/mysql à l’intérieur du conteneur :
[Unit]
Description=MariaDB container
[Container]
Image=docker.io/mariadb:latest
Environment=MYSQL_ROOT_PASSWORD=rootpassword
Environment=MYSQL_USER=testuser
Environment=MYSQL_PASSWORD=testpassword
Environment=MYSQL_DATABASE=testdb
Volume=mariadb-volume.volume:/var/lib/mysql
[Install]
WantedBy=multi-user.targetLorsque nous utilisons un volume nommé, Systemd lui attribue automatiquement une dépendance dans l’unité de service qu’il génère pour notre conteneur. Pour permettre à systemd de régénérer les services requis, une fois de plus, nous utilisons la commande daemon-reload. Une fois que nous (re)démarrons le conteneur MariaDB, le volume est créé automatiquement, comme nous pouvons le vérifier en utilisant l’utilitaire de ligne de commande podman :
podman volume lsComme prévu, notre volume apparaît dans la liste générée par la commande :
DRIVER VOLUME NAME
local systemd-mariadb-volumeNous pouvons également vérifier que le volume est monté sur /var/lib/mysql à l’intérieur du conteneur en utilisant la commande podman inspect, en passant le nom du conteneur en argument et en jetant un coup d’œil à la section « Mounts » :
podman inspect systemd-mariadb-serviceVoici la section pertinente de la sortie :
"Mounts": [
{
"Type": "volume",
"Name": "systemd-mariadb-volume",
"Source": "/home/doc/.local/share/containers/storage/volumes/systemd-mariadb-volume/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "",
"Options": [
"nosuid",
"nodev",
"rbind"
],
"RW": true,
"Propagation": "rprivate"
}
],Utilisation des montages de liaison
Que se passe-t-il si nous voulons utiliser des montures de liaison au lieu de volumes nommés ? Les bind-mounts sont utiles pendant le développement, car ils nous permettent de monter des fichiers hôtes à l’intérieur du conteneur. L’inconvénient de l’utilisation de bind-mounts est que les conteneurs deviennent dépendants du système de fichiers de l’hôte. Pour utiliser un bind-mount à l’intérieur d’une unité « .container », il suffit de spécifier le chemin relatif ou absolu du fichier hôte que nous voulons monter. Supposons, par exemple, que nous voulions lier le répertoire /var/lib/mysql à l’intérieur du conteneur, au répertoire ~/mysql sur l’hôte. Voici ce que l’on pourrait écrire dans l’unité « .container " :
[Unit]
Description=MariaDB container
[Container]
Image=docker.io/mariadb:latest
Environment=MYSQL_ROOT_PASSWORD=rootpassword
Environment=MYSQL_USER=testuser
Environment=MYSQL_PASSWORD=testpassword
Environment=MYSQL_DATABASE=testdb
Volume=%h/mysql:/var/lib/mysql
[Install]
WantedBy=multi-user.targetDans l’exemple ci-dessus, vous pouvez remarquer que nous avons utilisé l’espace réservé %h, qui est automatiquement étendu par Systemd au chemin absolu de notre propre répertoire HOME. Il est également possible d’utiliser des chemins d’accès relatifs, qui sont résolus en fonction de la position du fichier d’unité.
Création de réseaux
Pour créer une pile composée de plusieurs conteneurs, de la même manière que nous le faisons avec docker-compose, nous devons mettre des conteneurs dans le même réseau, afin qu’ils puissent communiquer entre eux. Pour créer un réseau avec Quadlet, on peut utiliser des unités avec l’extension « .network ».
Comme c’est le cas pour les conteneurs et les volumes, par défaut, les réseaux sont nommés d’après le fichier unitaire dans lequel ils sont définis, ainsi que le préfixe « systemd-« . Nous pouvons fournir explicitement un nom, ou toute autre option spécifique au réseau, dans la section [Réseau] du fichier. Dans l’exemple ci-dessous, nous spécifions l’adresse du sous-réseau et de la passerelle pour le réseau (c’est l’équivalent de l’exécution de podman avec les options --subnet 192.168.30.0/24 et --gateway 192.168.30.1) :
[Unit]
Description=MariaDB Network
[Network]
Subnet=192.168.30.0/24
Gateway=192.168.30.1Nous enregistrons le fichier sous le nom ~/.config/containers/systemd/mariadb.network. Pour « mettre » un conteneur dans un réseau spécifique, nous utilisons l’option Réseau à l’intérieur de la section « Conteneur » de son unité de conteneur. Le conteneur MariaDB que nous avons défini précédemment, devient :
[Unit]
Description=MariaDB container
[Container]
Image=docker.io/mariadb:latest
Environment=MYSQL_ROOT_PASSWORD=rootpassword
Environment=MYSQL_USER=testuser
Environment=MYSQL_PASSWORD=testpassword
Environment=MYSQL_DATABASE=testdb
Volume=mariadb-volume.volume:/var/lib/mysql
Network=mariadb.networkCréation d’une pile multi-conteneurs
Nous avons un conteneur qui exécute notre serveur MariaDB. Pour ajouter un moyen facile de gérer notre base de données via une interface web, nous pouvons créer un conteneur basé sur phpMyAdmin. Pour que les deux conteneurs puissent communiquer entre eux, il faut les mettre dans le même réseau.
Étant donné que le conteneur phpMyAdmin, pour fonctionner correctement, nécessite que le serveur MariaDB soit actif et en cours d’exécution, nous pouvons déclarer cette dépendance comme nous le ferions pour n’importe quel autre service Systemd, avec les options Requires et After dans la section « [Unit] ». Le premier établit une dépendance dure à l’égard du service rendu comme valeur ; Ce dernier garantit que notre service commence après celui-ci. D’ailleurs, si vous n’êtes pas familier avec Systemd, vous pouvez jeter un coup d’œil à notre tutoriel sur la création d’un service Systemd. Voici à quoi ressemble l’unité de conteneur pour phpMyAdmin :
[Unit]
Description=phpMyAdmin container
Requires=mariadb-service.service
After=mariadb-service.service
[Container]
Image=docker.io/phpmyadmin:latest
Network=mariadb.network
Environment=PMA_HOST=systemd-mariadb-service
PublishPort=8080:80
[Install]
WantedBy=multi-user.targetDans l’exemple ci-dessus, nous avons également utilisé l’option PublishPort, qui est l’équivalent de podman -p (--publish) : elle est utilisée pour mapper un port hôte à un port conteneur. Dans ce cas, nous avons mappé le port 8080 sur le système hôte, au port 80 à l’intérieur du conteneur.
Nous avons également fourni une valeur pour la variable d’environnement PMA_HOST, via l’option Environment : celle-ci est utilisée pour spécifier l’adresse du serveur de base de données (dans ce cas, nous avons utilisé le nom du conteneur MariaDB, qui est résolu à l’adresse réelle). Notez que nous avons utilisé le nom du conteneur MariaDB comme valeur de la variable d’environnement, et non le nom de l’unité « .container ». Pour démarrer notre nouvelle configuration, une fois de plus, nous exécutons :
systemd --user daemon-reloadEnsuite, nous pouvons démarrer le service « phpmyadmin-service » généré, qui, à son tour, exécute le conteneur phpMyAdmin. Comme il a une dépendance dure sur celui de MariaDB, ce dernier démarrera automatiquement aussi. Nous devrions être en mesure de joindre phpMyadmin à l’adresse « localhost :8080 ». Pour se connecter, nous pouvons utiliser les informations d’identification spécifiées dans l’unité de conteneur MariaDB :
Réflexions finales
Dans ce tutoriel, nous avons appris à créer et à exécuter des conteneurs, des volumes et des réseaux Podman sous Systemd à l’aide de Quadlet. Au lieu de définir des piles multi-conteneurs dans un seul fichier, comme nous le faisons avec docker-compose, avec Quadlet, nous définissons des conteneurs, des volumes et des réseaux à l’aide d’unités Systemd dédiées.

