Recherche de site Web

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 didacticiel, nous apprenons comment utiliser Quadlet pour créer des conteneurs, des réseaux et des volumes Podman, et comment créer des piles multi-conteneurs.

Dans ce didacticiel, vous apprendrez :

  • 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 basique : créer un conteneur MariaDB

Dans ce premier exemple basique, 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.target

Avec ces quelques lignes, nous avons défini un conteneur basé sur la dernière image officielle 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 « Conteneur », dans laquelle on peut spécifier des options qui sont les équivalents de celles que l'on peut passer à la ligne de commande Podman. La seule option obligatoire 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 qu'utilisateur non privilégié, nous l'enregistrons sous ~/.config/containers/systemd. Dans cet exemple, nous utiliserons cette dernière approche et enregistrerons notre unité « .container » sous ~/.config/containers/systemd/mariadb-service.container. Pour permettre à systemd de générer un service basé sur l'unité conteneur, nous exécutons la commande suivante :

$ systemctl --user daemon-reload

Après avoir exécuté la commande, nous pouvons jeter un œil au service généré en exécutant :

$ systemctl --user cat mariadb-service

Pour démarrer le conteneur, comme tout autre service, nous pouvons exécuter :

$ systemctl --user start mariadb-service

La première fois que nous le lançons, le service peut mettre 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 ps

La commande renvoie le résultat suivant, 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-service

Comme vous l'avez peut-être remarqué, par défaut, le conteneur est nommé d'après le fichier unité « .container » plus le préfixe « systemd- » (« systemd-mariadb-service », dans ce cas). Pour attribuer explicitement un nom au conteneur, nous pouvons cependant le passer comme 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 souhaitons que les données de notre base de données persistent même si nous supprimons 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 ~/.config/containers/systemd/mariadb-volume.volume. Pour demander 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 sur le 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.target

Lorsque 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 laisser systemd régénérer les services requis, nous utilisons à nouveau 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 ls

Comme prévu, notre volume apparaît dans la liste générée par la commande :

DRIVER        VOLUME NAME
local         systemd-mariadb-volume

Nous 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 comme argument et en jetant un œil aux « Montages » section:

$ podman inspect systemd-mariadb-service

Voici la section pertinente du résultat :

"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"
     }
],

Utiliser des supports de liaison

Que se passe-t-il si nous voulons utiliser des montages liés au lieu de volumes nommés ? Les montages liés 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 des montages liés est que les conteneurs deviennent dépendants du système de fichiers hôte. Pour utiliser un bind-mount dans une unité « .container », nous spécifions simplement le chemin relatif ou absolu du fichier hôte que nous voulons monter. Supposons, par exemple, que nous souhaitions monter en liaison le répertoire /var/lib/mysql à l'intérieur du conteneur, vers le 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.target

Dans l'exemple ci-dessus, vous pouvez remarquer que nous avons utilisé l'espace réservé %h, qui est automatiquement développé par Systemd jusqu'au chemin absolu de notre propre répertoire HOME. Il est également possible d'utiliser des chemins relatifs, qui sont résolus par rapport à la position du fichier unité.

Créer des réseaux

Pour créer une pile composée de plusieurs conteneurs, de la même manière que ce que nous faisons avec docker-compose, nous devons mettre les conteneurs dans le même réseau, afin qu'ils puissent communiquer entre eux. Pour créer un réseau avec Quadlet, nous pouvons 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 unité dans lequel ils sont définis, plus le préfixe « systemd- ». Nous pouvons explicitement fournir un nom, ou toute autre option spécifique au réseau, dans la section [Network] du fichier. Dans l'exemple ci-dessous, nous spécifions le sous-réseau et l'adresse de passerelle du réseau (c'est l'équivalent d'exécuter podman avec le --subnet 192.168.30.0/24 et le --gateway 192.168.30.1  :

[Unit]
Description=MariaDB Network

[Network]
Subnet=192.168.30.0/24
Gateway=192.168.30.1

Nous enregistrons le fichier sous ~/.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é 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.network

Création d'une pile multi-conteneurs

Nous avons un conteneur exécutant notre serveur MariaDB. Pour ajouter un moyen simple 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.

Puisque 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 tout autre service Systemd, avec les champs Requires et . Options Après dans la section « [Unité] ». Le premier établit une forte dépendance à l’égard du service considéré comme sa valeur ; ce dernier garantit que notre service démarre après cela. D'ailleurs, si vous n'êtes pas familier avec Systemd, vous pouvez consulter notre tutoriel sur la façon de créer un service Systemd. Voici à quoi ressemble l’unité 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.target

Dans 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 Environnement : celle-ci permet de 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 en adresse réelle). Notez que nous avons utilisé le nom du conteneur MariaDB comme valeur de la variable d'environnement, pas le nom de l'unité « .container ». Pour démarrer notre nouvelle configuration, encore une fois, nous exécutons :

$ systemd --user daemon-reload

Ensuite, nous pouvons démarrer le service « phpmyadmin-service » généré, qui, à son tour, exécute le conteneur phpMyAdmin. Comme il dépend fortement de celui de MariaDB, ce dernier démarrera également automatiquement. Nous devrions pouvoir joindre phpMyadmin à l'adresse « localhost:8080 ». Pour nous connecter, nous pouvons utiliser les informations d'identification spécifiées dans l'unité du conteneur MariaDB :

Pensées finales

Dans ce didacticiel, nous avons appris comment 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.

Articles connexes: