LINUX:Conteneur
But
Un conteneur est une unité de logiciel qui fournit un mécanisme d'emballage qui abstrait le code et toutes ses dépendances pour rendre l'application ayant une construction rapidement et fiable. Ce logiciel s'exécute de façon isolée vis-à-vis des autres applications.
Nous aborderons les bases de ce concept. Nous l'utiliserons sur une machine utilisant l'OS Linux de la distribution Fedora. Les conteneurs utilisés dans les exemples mis en place, auront majoritairement une base Linux des distributions Debian ou Ubuntu.
Concept
Un conteneur travaille de façon analogue à une machine virtuelle mais plus légère. Conventionnellement il ne comprend qu'une application qui va travailler isolément des autres applications de la machine hôte (Linux Fedora). Il n'aura des interactions avec d'autres applications qu'au travers du réseau comme une machine indépendante.
Comparons un conteneur à une machine virtuelle (VM) qui tournent tous deux sur une machine hôte équipée de son propre OS et de logiciels propres. Un conteneur et une machine virtuelle s'exécute comme un parasite de la machine hôte.
Une machine virtuelle se base sur une partie des ressources matérielles de la machine hôte et accapare ces ressources. Il met en oeuvre l'ensemble des composants d'une machine: son OS qui va interagir avec ces ressources matérielles et tout le cortège des logiciels nécessaires à ses tâches. Cet OS peut être n'importe lequel indépendamment de celui de la machine hôte. Il aura besoin de ressources comme s'il tournait sur une machine physique indépendante. Par ce fait, il en découle une machine physique ayant des ressources très importantes. Le seul bénéfice, vis-à-vis des autres machines virtuelles tournant sur la même machine hôte, réside dans la mutualisation d'une partie de ses ressources avec les autres machines virtuelles pour autant que l'ensemble des ressources nécessaires ne dépassent pas les capacités de la machine hôte et selon ses besoins propres à un moment donné qui fluctuent en fonction des demandent qui lui sont demandées.
De son côté, un conteneur va se baser, non pas directement sur les ressources matérielles de la machine hôte mais sur l'OS (système opératoire) de la machine hôte. Il va donc contenir le nécessaire pour faire le logiciel ciblé et ses interactions avec le réseau afin d'interagir avec d'autres conteneurs et d'autres machines au travers la machine hôte. Il va se comporter comme une micro-machine isolée du reste du système de la machine hôte et des autres conteneurs tout en n'utilisant que le kernel ou noyau de la machine hôte qui elle gère les ressources matérielles de la machine physique. Par ce fait, le logiciel de ce conteneur ne pas interférer avec les autres logiciels tournant sur la même machine, hôte ou conteneurs. Et corolaire, les ressources utilisées sont très nettement moindres, tout en devant être compatibles avec l'OS de la machine hôte au travers de son kernel ou noyau.
Tous deux apportent une couche de sécurité supplémentaire à tout intrusion non désirée ou dégâts collatéraux vis-à-vis des autres applications tournant sur cette machine.
Installation
Comme les machines virtuelles, les conteneurs ont besoin de leur gestionnaire. Mais celui utilisé n'a pas besoin d'un service dédié au contraire de Docker. Nous utilisons "PodMan".
Nous l'installons grâce à la commande de ligne suivante:
dnf install podman toolbox
Cockpit
Le logiciel Cockpit possède un module permettant de gérer les conteneurs.
Nous allons l'ajouter via la commande de ligne suivante:
dnf install cockpit-podman
Si l'adresse IP de notre machine hôte est "192.168.1.66", on peut accéder à Cockpit via l'URL:
https://192.168.1.66:9090
Un écran d'authentification demande le nom d'utilisateur Linux de la machine hôte et son mot de passe.
Un conteneur est créé et utilisé via un nom d'utilisateur spécifique Linux sur la machine hôte. L'authentification doit se faire via ce nom d'utilisateur qui seul peut voir et gérer ce conteneur. Par exemple, un conteneur créé sous l'utilisateur "adminct" ne pourra pas être vu par l'utilisateur "root" via l'interface Web de Cockpit.
Dans l'interface qui s'ouvre, on choisit le point "Conteneurs Podman" dans le menu de gauche.
Mode Root et RootLess
Un conteneur peut être utilisé sous l'utilisateur "root" ou tout autre utilisateur de la machine hôte n'ayant pas des droits administrateur (RootLess). Le cycle de vie d'un conteneur est identique dans les deux cas. Il n'y aura que quelques particularités lors de l'exécution automatique des conteneurs.
En première partie, nous gérerons les conteneurs sous l'Utilisateur "root". Ensuite nous aborderons le cas d'utilisation sous un utilisateur non root (RootLess).
L'intérêt est d'ajouter une couche de protection. Si le conteneur est compromis, le pirate n'aura que les droits réduits de cet utilisateur.
On peut pousser plus loin en créant un conteneur par utilisateur afin de complexifier la sécurité. Chaque conteneur est sécurisé des autres.
Cycle de vie d'un conteneur
Il existe la possibilité de construire et d'exécuter, via la couche Systemd, de tout nouveau conteneur. Nous ne l'utiliserons pas car nous avons préféré décomposer toutes les étapes de vie d'un conteneur afin de mieux comprendre sa mise en place. L'utilisation via Systemd est adaptée pour une implémentation clé en main, standardisée sur un ensemble de machines.
De plus, nous n'aborderons pas la facette de création de nos propres environnements de conteneurs ou images. Il existe un grand nombre d'images pour les principales applications; il existe même de nombreuses versions pour une même application. Nous chercherons parmi elles.
Le cycle de vie d'un conteneur est le suivant, sur base d'un choix dune application précise:
- Phase de création et d'utilisation:
- On recherche le nom d'une image de l'application ciblée.
- On récupère l'image choisie.
- On crée un volume qui sera utilisé par notre conteneur; ce volume qui peut être un répertoire ou un fichier permet de personnaliser le conteneur, le conteneur lui-même étant volatile.
- On crée un conteneur sur base de cette image; cette création est accompagnée d'un certain nombre de paramètres qui servent à adapter cette application à nos besoins.
- On démarre le conteneur.
- Au besoin, on adapte l'hôte afin de faciliter l'utilisation de cette application par les clients.
- Phase d'élimination d'un conteneur:
- On arrête le conteneur.
- On efface le conteneur.
- On efface les volumes de ce conteneur.
- On efface l'image associée.
- On élimine les adaptations faites au niveau de l'hôte.
Evidemment ce cycle peut se faire de façon partielle spécialement dans sa phase de recherche de la bonne configuration. Par exemple, si le paramétrage ne nous convient pas; on se limite à l'arrêt de ce conteneur et à sa destruction pour pouvoir recréer ce même conteneur avec d'autres options.
Découverte de notre premier conteneur
On va commencer par découvrir les principales étapes du cycle d'un conteneur. Nous avons opté pour la création d'un site Web statique. Nous utiliserons un serveur Web Apache: HTTPD. Nous utiliserons une image toute faite.
La très grande majorité des commandes de ligne se font avec le logiciel "podman" que nous avons installé en début d'article. Nous l'utilisons sous l'utilisateur "root".
Tout ce nous ferons par la suite sera enregistré dans le dossier "/var/lib/containers/storage".
Recherche d'une image
La première étape est la recherche une image. Une image est un paquet qui contient tout le nécessaire pour créer un conteneur.
Pour cette recherche, Linux Fedora possède une liste de sites où chercher les images. On peut en avoir une idée en consultant le site: https://hub.docker.com/
Pour effectuer cette recherche nous lançons la commande:
podman search httpd
qui donne la longue liste suivante:
NAME DESCRIPTION registry.fedoraproject.org/f29/httpd docker.io/library/httpd The Apache HTTP Server Project docker.io/manageiq/httpd Container with httpd, built on CentOS for Ma... docker.io/paketobuildpacks/httpd docker.io/vulhub/httpd docker.io/openeuler/httpd docker.io/dockerpinata/httpd docker.io/centos/httpd docker.io/jokerjack/httpd base image: buxybox, running httpd server,... docker.io/manasip/httpd docker.io/e2eteam/httpd docker.io/6sycho/httpd busybox httpd /docker run --name -d mageedu/... docker.io/puyanhong/httpd busybox httpd , docker run --name NAME -d p... docker.io/wanliduxing/httpd busybox httpd docker run --name NAME -d ma... docker.io/ghtl/httpd busybox httpd docker run --name NAME -d ght... docker.io/litaotaodocker/httpd busybox httpd docker run -name NAME -d litao... docker.io/liubaoyu/httpd busybox httpd docker run --name NAME -d... docker.io/ohcoder/httpd busybox httpd docker run --name NAME -d ohc... docker.io/muda/httpd busybox httpd docker run --name NAME -d ma... docker.io/dockerptu/httpd busybox httpd 'docker run --name NAME -d... docker.io/lolhens/httpd Apache httpd 2 Server docker.io/vishakkv/httpd spinup httpd in centos 7 docker.io/amd64/httpd The Apache HTTP Server Project docker.io/tangxj/httpd busybox-httpd,you should use this command: d... docker.io/went2675/httpd docker --name NAME -d went2675/httpd docker.io/futdryt/httpd
Nous retiendrons la seconde, l'officielle: "docker.io/library/httpd" dont le détail peut être consulté à l'URL: https://hub.docker.com/_/httpd
Ce site vous explique comment l'utiliser.
Récupération de l'image
La seconde étape consiste à récupérer cette image avec la commande:
podman pull docker.io/library/httpd
Cette récupération consiste à récupérer le "blob" ou module principal et toutes ses dépendances.
Trying to pull docker.io/library/httpd:latest... Getting image source signatures Copying blob c4a216db6600 done | Copying blob 26c307b5e35a done | Copying blob 4f4fb700ef54 done | Copying blob c271d17baba2 done | Copying blob 04951bf53bdd done | Copying blob 2c2b87df2933 done | Copying config 46ababc59d done | Writing manifest to image destination 46ababc59dbd026ab02d09961f28873185d8331b0939954aa24f57b55fca7244
La dernière ligne correspond à l'ID de l'image.
On peut lister les images déjà téléchargées:
podman image list
qui donne:
REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/httpd latest 46ababc59dbd 8 days ago 120 MB
On peut lister les modules associés:
podman image tree docker.io/library/httpd
qui donne:
Image ID: 46ababc59dbd Tags: [docker.io/library/httpd:latest] Size: 120.3MB Image Layers ├── ID: 6f9432833129 Size: 81.05MB ├── ID: dd0da4e32c9e Size: 2.56kB ├── ID: 623762dd73ce Size: 1.024kB ├── ID: 4db9e02e6229 Size: 6.041MB ├── ID: c2b626d7d8f8 Size: 33.13MB └── ID: 7f5555156aba Size: 3.584kB Top Layer of: [docker.io/library/httpd:latest]
On peut consulter ses caractéristiques:
podman image inspect docker.io/library/httpd
La partie suivante est intéressante:
...
"Config": {
"ExposedPorts": {
"80/tcp": {}
},
"Env": [
"PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HTTPD_PREFIX=/usr/local/apache2",
"HTTPD_VERSION=2.4.68",
"HTTPD_SHA256=68c74d4df38c26bed4dfbdb8f3baf1eb532f3872357becc1bba5d136f6b63c06",
"HTTPD_PATCHES="
],
"Cmd": [
"httpd-foreground"
],
"WorkingDir": "/usr/local/apache2",
"StopSignal": "SIGWINCH"
},
...
Cette partie nous sera utile pour affiner la configuration de notre futur conteneur.
Si on ne veut plus de cette image, on peut l'éliminer:
podman image rm docker.io/library/httpd
Attention, il ne doit plus exister de conteneur associé.
Création d'un conteneur de base
Nous allons créer notre premier conteneur afin de l'explorer avant sa création définitive.
Cette commande est la suivante, réduite au minimal opérationnel:
podman create --name mysite --publish 8081:80 docker.io/library/httpd
Elle comporte bon nombre d'options; nous n'en avons retenu que deux:
- name: nomme notre conteneur en plus de son ID, ce qui sera plus pratique pour l'utiliser.
- publish: Il permet de faire apparaître le service qui tourne dans notre conteneur sur notre hôte. Dans le conteneur, le port 80/tcp est à l'écoute et sur la machine hôte, il apparaîtra selon le port tcp/8081. On pourrait en mode "root" utiliser le port tcp/80 au lieu de tcp/8081 mais si nous avons plusieurs conteneurs de sites Web, il ne peut n'y en avoir qu'un avec le port tcp/80. On verra plus loin comment contourner ce problème. Si tout va bien, la commande nous retourne l'ID du nouveau conteneur.
Le dernier argument reprend le nom de l'image.
Cette opération est analogue à une installation d'un nouveau système opératoire (OS) sur un disque dur à partie d'une image placée sur un média tel une clé USB.
On peut lister les conteneurs existants:
podman container list --all
L'option "--all" sert à tous les lister; si cette option n'est pas présente, seul les conteneurs actifs sont listés. Cette commande donne:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 83e0e2eda21b docker.io/library/httpd:latest httpd-foreground 29 minutes ago Created 0.0.0.0:8081->80/tcp mysite
Démarrage du conteneur
Maintenant que notre micro-machine est créée, on va la démarrer:
podman start mysite
ou
podman container start mysite
Conséquences de ce lancement
Notre commande du point précédent:
podman container list
permet de constater que notre conteneur a changé de statut:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 83e0e2eda21b docker.io/library/httpd:latest httpd-foreground 39 minutes ago Up 2 minutes 0.0.0.0:8081->80/tcp mysite
De même est apparu de nouveaux processus:
ps axfu
qui donne:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND ... root 113754 0.0 0.0 10400 2712 ? Ss 18:08 0:00 \_ /usr/bin/conmon --api-version 1 -c 83e0e2eda21bea8eded900a3e0c5e root 113758 0.0 0.1 6224 4996 ? Ss 18:08 0:00 \_ httpd -DFOREGROUND 33 113763 0.0 0.1 1210968 4404 ? Sl 18:08 0:00 \_ httpd -DFOREGROUND 33 113764 0.0 0.1 1210968 4392 ? Sl 18:08 0:00 \_ httpd -DFOREGROUND 33 113766 0.0 0.1 1210968 4396 ? Sl 18:08 0:00 \_ httpd -DFOREGROUND
On remarque qu'un processus "conmon" est lancé qui exécute le micro-système opératoire (micro-OS) de notre conteneur "mysite" qui, à son tour, lance quatre autres processus, ici le serveur Web "httpd". On remarquera que le nom d'utilisateur n'est pas "apache" comme sur notre système hôte. Il est inconnu de notre hôte et est propre au conteneur "UID=33". Il correspond à l'utilisateur "www-data".
En corolaire, un nouveau port est à l'écoute "tcp/8081" comme attendu:
netstat -nltp
qui donne
Connexions Internet actives (seulement serveurs) Proto Recv-Q Send-Q Adresse locale Adresse distante Etat PID/Program name ... tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN 113754/conmon ...
Le démarrage de ce conteneur s'accompagne de nouveaux interfaces réseaux liés à ce dernier:
ip address
qui donne:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp0s25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:1c:c0:79:7c:12 brd ff:ff:ff:ff:ff:ff
altname enx001cc0797c12
inet 192.168.1.66/24 brd 192.168.1.255 scope global noprefixroute enp0s25
valid_lft forever preferred_lft forever
3: podman0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether fe:8d:8c:60:67:58 brd ff:ff:ff:ff:ff:ff
inet 10.88.0.1/16 brd 10.88.255.255 scope global podman0
valid_lft forever preferred_lft forever
inet6 fe80::fc8d:8cff:fe60:6758/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
4: veth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master podman0 state UP group default qlen 1000
link/ether fa:7c:b0:42:9b:fc brd ff:ff:ff:ff:ff:ff link-netns netns-47970c99-3958-82f8-8b6f-4cdd76dbbf4d
inet6 fe80::acb4:d6ff:fe10:d1b0/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
L'interface "podman0" correspond à notre hôte vu du côté du réseau des conteneurs avec l'adresse IPv4 "10.88.0.1/16". Le suivant correspond à notre conteneur. Si nous avions un second conteneur actif, on aurait un cinquième interface. On verra son adresse IPv4 en rentrant dans ce conteneur. Il appartiendra au réseau "10.88.0.0/16".
De même la table de routage est amandée:
ip route
qui donne:
default via 192.168.1.1 dev enp0s25 proto static metric 100 10.88.0.0/16 dev podman0 proto kernel scope link src 10.88.0.1 192.168.1.0/24 dev enp0s25 proto kernel scope link src 192.168.1.66 metric 100
Notre hôte avec l'adresse IPv4 "10.88.0.1" sert de route vers le réseau des conteneurs.
On peut également retrouver nombre d'informations en inspectant ce conteneur:
podman container inspect mysite
Site Web
C'est ne moment de tester notre site.
On lance dans notre navigateur Internet préféré, l'URL: http://192.168.1.66:8081/
On a la phrase suivante qui s'affiche:
It works!
Note: N'oubliez pas de désactiver le FireWall ou d'ouvrir le port tcp/8081.
Travailler dans le conteneur
Il est possible d'ouvrir une console dans ce conteneur:
podman exec -it mysite bash
ou:
podman container exec -it mysite bash
On lance l'interpréteur de commande "bash" en mode interactif (option: "-i") dans un terminal (option: "-t").
On a un prompt. En y lançant la commande:
cat /etc/os-release
on a:
PRETTY_NAME="Debian GNU/Linux 13 (trixie)" NAME="Debian GNU/Linux" VERSION_ID="13" VERSION="13 (trixie)" VERSION_CODENAME=trixie DEBIAN_VERSION_FULL=13.6 ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/"
On remarque qu'on est en présence d'une distribution de Linux Debian.
On ressort avec:
exit
Mais on remarque vite qu'on est très limité dans les commandes. En effet, on a affaire à un OS minimum.
On va procéder à quelques installations. Notons que celles-ci disparaitront avec la destruction du conteneur.
Voici quelques commandes pour aider la consultation du réseau, des processus et de la navigation aisée (mc ou Midnight Commander):
podman exec -it mysite /usr/bin/apt -y update podman exec -it mysite /usr/bin/apt -y upgrade podman exec -it mysite /usr/bin/apt -y install mc net-tools procps iproute2 iputils-ping
On rentre à nouveau dans le conteneur.
Et on exécute:
ps axfu
qui donne:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 831 0.0 0.0 4328 3764 pts/0 Ss 17:20 0:00 bash root 833 0.0 0.0 6400 3764 pts/0 R+ 17:20 0:00 \_ ps axfu root 1 0.0 0.1 6224 4996 ? Ss 16:08 0:00 httpd -DFOREGROUND www-data 3 0.0 0.1 1210968 4404 ? Sl 16:08 0:00 httpd -DFOREGROUND www-data 4 0.0 0.1 1211032 4992 ? Sl 16:08 0:00 httpd -DFOREGROUND www-data 6 0.0 0.1 1210976 4408 ? Sl 16:08 0:00 httpd -DFOREGROUND
On remarque notre session "root" en mode terminal et le serveur Web "httpd".
Et pour le réseau:
ip address
on a:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host proto kernel_lo
valid_lft forever preferred_lft forever
2: eth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 86:15:1c:84:d9:d2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.88.0.2/16 brd 10.88.255.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::8415:1cff:fe84:d9d2/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
De même:
ip route
on a:
default via 10.88.0.1 dev eth0 proto static metric 100 10.88.0.0/16 dev eth0 proto kernel scope link src 10.88.0.2
Si maintenant on va dans le dossier suivant:
cd /usr/local/apache2/htdocs
on y trouve le fichier "index.html" qui contient le message affiché dans notre navigateur Internet.
Ces informations vont nous servir pour l'étape suivante. On peut sortir.
Arrêt du conteneur
Ce conteneur était conçu afin d'apprivoiser le concept de conteneur.
On va l'arrêter:
podman stop mysite
ou:
podman container stop mysite
Destruction du conteneur
On n'en a plus besoin, donc on l'efface:
podman container rm mysite
Le cycle de ce conteneur est terminé.
Note
Au lieu d'utiliser les commandes:
podman create ... podman start ...
On peut les coupler avec la commande:
podman run -d ...
Ses arguments sont les mêmes que pour "podman create ..."
Si on ajoute l'option "-rm":
podman run -d -rm ...
La commande:
podman stop ...
sera équivalente à:
podman stop ... podman container rm ...
Réseau
Le logiciel "podman" intègre une gestion de réseaux liés aux conteneurs. Intégré à l'installation, un réseau est créé: "podman". On a remarqué sa présence en consultant les interfaces réseaux suite à l'activation du conteneur "mysite": "podman0". Mais on peut en créer d'autres.
Pour voir la liste de ces réseaux, on exécute la commande:
podman network list
qui donne:
NETWORK ID NAME DRIVER 2f259bab93aa podman bridge
On peut voir le détail de ce réseau:
podman network inspect podman
qui donne:
[
{
"name": "podman",
"id": "2f259bab93aaaaa2542ba43ef33eb990d0999ee1b9924b557b7be53c0b7a1bb9",
"driver": "bridge",
"network_interface": "podman0",
"created": "2026-08-13T18:38:45.98474812+02:00",
"subnets": [
{
"subnet": "10.88.0.0/16",
"gateway": "10.88.0.1"
}
],
"ipv6_enabled": false,
"internal": false,
"dns_enabled": false,
"ipam_options": {
"driver": "host-local"
},
"containers": {
"83e0e2eda21bea8eded900a3e0c5e53e8b584380f55c004ef2158b75d639be32": {
"name": "mysite",
"interfaces": {
"eth0": {
"subnets": [
{
"ipnet": "10.88.0.2/16",
"gateway": "10.88.0.1"
}
],
"mac_address": "86:15:1c:84:d9:d2"
}
}
}
}
}
]
Il est de type "pont" ou "bridge".
Cette commande est exécutée alors que le conteneur "mysite" était actif. On le voit dans la section "containers", les informations de celui que nous venons de lancer. Il a l'adresse IPv4 "10.88.0.2/16" et son routeur est celle de notre machine hôte "10.88.0.1".
Pour en créer un nouveau, on exécute la commande suivante:
podman network create --subnet 172.30.1.0/24 mynetwork
Ce réseau se nomme "mynetwork" et couvre l'adressage "172.30.1.0/24".
On peut l'éliminer comme suit:
podman network rm mynetwork
Il est à remarquer que le réseau "podman" est présent pour tout utilisateur. Par contre, ceux créés ne sont accessibles que par l'utilisateur qui l'a créé.
Volume
Un conteneur comprend un ensemble de fichiers et de répertoires découlant du déploiement de son image. Mais si on le détruit tout disparaît même le paramétrage ou les mises à jour. Par exemple, quand on utilise un logiciel tel WordPress, on ajoute des documents, des pages,... et le paramétrage est stocké dans une base de données. Et le tout est inaccessible directement.
La solution est la création d'un volume. Ce volume peut comprendre un fichier ou toute une arborescence de fichiers et répertoires. Ce volume sera lié à un endroit particulier du conteneur lors de sa création et remplacera ce qui existait dans le conteneur.
Il y a divers intérêts:
- Le contenu du volume est directement visible et gérable par le conteneur et l'hôte.
- Dans le cas de la destruction du conteneur, le contenu du volume n'est pas détruit et peu donc être réutilisé par un autre conteneur ou récupéré.
Par contre,
- le contenu de ce volume est géré et utilisé par le conteneur et donc il faut que les droits et privilèges soient ceux du conteneur et les utilisateurs et les groupes du conteneur sont différents de l'hôte. Il faut faire très attention à ce point au risque que les services fournis par les conteneurs ne soient pas au rendez-vous.
Pour créer un conteneur nommé, par exemple, "htmlasbl", on lance la commande:
podman volume create htmlasbl
Le dossier correspondant est créé: "/var/lib/containers/storage/volumes/htmlasbl". On peut placer, modifier, consulter,... tout fichier ou répertoire à l'intérieur du sous-dossier "_data".
On peut lister tous les volumes existant avec la commande:
podman volume list
qui donne:
DRIVER VOLUME NAME local htmlasbl
Et son détail:
podman volume inspect htmlasbl
qui donne:
[
{
"Name": "htmlasbl",
"Driver": "local",
"Mountpoint": "/var/lib/containers/storage/volumes/htmlasbl/_data",
"CreatedAt": "2026-08-14T13:49:56.862714111+02:00",
"Labels": {},
"Scope": "local",
"Options": {},
"MountCount": 0,
"NeedsCopyUp": true,
"NeedsChown": true,
"LockNumber": 1
}
]
On peut le détruire par la commande:
podman volume rm htmlasbl
Démarrage automatique des conteneurs
Si on redémarre notre hôte, tous les conteneurs actifs sont arrêtés mais ne redémarrent pas.
Pour pallier à ce problème, on doit activer un service spécifique et on l'active ensuite:
systemctl enable podman-restart.service systemctl start podman-restart.service
De plus il faut ajouter l'option "--restart=always" lors de la création des conteneurs concernés.
Création des conteneurs
Nous allons créer cinq conteneurs dans le but de présenter quelques cas simples.
Conteneur sur base de l'image "httpd"
Maintenant qu'on a découvert les bases d'un conteneur, on va affiner notre paramétrage.
Pour ce premier cas, on a pour but créer un conteneur pour un site Web statique existant sur base d'une image "httpd". Le détail peut être consulté à l'URL: https://hub.docker.com/_/httpd
On commence par créer un volume où on placera le contenu de notre site:
podman volume create htmlasbl
En second, on crée un conteneur sur base de notre image "docker.io/library/httpd".
podman create \ --name myasbl \ --restart=always \ --hostname ctasbl.home.dom \ --network podman:ip=10.88.0.11 \ --publish 127.0.0.1:8081:80 \ --volume htmlasbl:/usr/local/apache2/htdocs \ docker.io/library/httpd
On a ajouté diverses options dont quelques-unes découlent de notre connaissances acquises aux points précédents/
- On nomme ce conteneur ("name"): "myasbl".
- L'option "--restart=always" enclenche le démarrage automatique du conteneur lors du redémarrage de l'hôte comme vu plus tôt.
- On donne un nom de machine ("hostname") au conteneur plutôt qu'un nom aléatoire: "ctasbl.home.dom", ce qui évite un message d'erreur du processus "httpd".
- L'option "network" nous sert à imposer l'adresse IPv4 du conteneur à "10.88.0.11" sur base du réseau "podman" vu plus haut.
- On publie le port tcp/80 du service HTTPD du conteneur au niveau de l'hôte: "tcp/127.0.0.1:8081". On remarque que ce service ne sera accessible que par l'hôte en local. On verra plus loin l'intégration de plusieurs services Web, visibles par tous.
- On a remarqué plus haut que le contenu du site se trouvait au niveau du conteneur dans le répertoire "/usr/local/apache2/htdocs". On va lier ce dossier au volume créé ci-dessus.
On peut lancer le conteneur:
podman start myasbl
En consultant le contenu du dossier "/var/lib/containers/storage/volumes/htmlasbl/_data", on y retrouve notre fichier "index.html" dont voici ses droits sous l'hôte:
ls -ln
qui donne:
total 4 -rw-r--r-- 1 501 50 191 7 nov 2025 index.html
On peut copier les fichiers et répertoires de notre site à la place de ce fichier. On adapte les droits d'accès et surtout le propriétaire:
chown -R 501:50 *
On peut tester localement ce site:
curl http://localhost:8081
ou
lynx http://localhost:8081
On peut également visualiser le journal du conteneur:
podman logs myasbl
qui donne:
[Fri Aug 14 12:00:18.868366 2026] [mpm_event:notice] [pid 1:tid 1] AH00489: Apache/2.4.68 (Unix) configured -- resuming normal operations [Fri Aug 14 12:00:18.877689 2026] [core:notice] [pid 1:tid 1] AH00094: Command line: 'httpd -D FOREGROUND' 10.88.0.1 - - [14/Aug/2026:12:59:33 +0000] "GET / HTTP/1.1" 200 2554
On remarque l'accès au site avec la commande "curl" en dernière ligne.
Conteneur sur base de l'image "mariadb"
Le second projet consiste à installer un site Web basé sur WordPress.
Mais pour cela, il nous faut une base de données de type MySql. En l'occurrence, nous recherchons une image "mariadb". Nous avons mis notre dévolu sur l'image "docker.io/library/mariadb:latest". Le détail peut être consulté à l'URL: https://hub.docker.com/_/mariadb
On commence par créer un volume où on placera le contenu de la base de données:
podman volume create dbmariadb
En second, on crée un conteneur sur base de notre image "docker.io/library/mariadb".
podman create \ --name mymariadb \ --restart=always \ --hostname ctmariadb.home.dom \ --network podman:ip=10.88.0.13 \ --publish 3307:3306 \ --env MARIADB_ROOT_PASSWORD='SpediaPwRoot' \ --env MARIADB_DATABASE='dbwp' \ --env MARIADB_USER='userwp' \ --env MARIADB_PASSWORD='SuiteInconnue72' \ --volume dbmariadb:/var/lib/mysql \ docker.io/library/mariadb:latest
On a ajouté diverses options dont quelques-unes découlent de notre connaissances acquises aux points précédents:
- On nomme ce conteneur ("name"): "mymariadb".
- L'option "--restart=always" enclenche le démarrage automatique du conteneur lors du redémarrage de l'hôte comme vu plus tôt.
- On donne un nom de machine ("hostname") au conteneur plutôt qu'un nom aléatoire: "ctmariadb.home.dom".
- L'option "network" nous sert à imposer l'adresse IPv4 du conteneur à "10.88.0.13" sur base du réseau "podman" vu plus haut.
- On publie le port tcp/3306 du service MARIADB du conteneur au niveau de l'hôte: "tcp/3307". On a changé au niveau de l'hôte le n° du port afin qu'on puisse à l'avenir créer d'autres conteneurs de base de données. On n'a pas limité son accès au port local de l'hôte car il sera accédé par un autre conteneur. Au niveau du FireWall de l'hôte, il n'est pas nécessaire d'ouvrir ce port car tout se passera au travers l'interface "lo" et d'un trafic interne qui est normalement ouvert.
- La base de données sera placée dans un volume créé ci-dessus et lié au niveau du conteneur dans le répertoire "/var/lib/mysql".
- Ensuite nous avons à notre disposition diverses variables d'environnement qui vont servir à créer la base de données et le schéma qui contiendra les données du site de WordPress.
- MARIADB_ROOT_PASSWORD: pour le mot de passe de l'utilisateur "root" de la base de données MariaDB.
- MARIADB_DATABASE: pour le nom du schéma qui contiendra les données du site de WordPress
- MARIADB_USER: pour le nom d'utilisateur ayant le droit d'accès au schéma "dbwp"
- MARIADB_PASSWORD: pour le mot de passe de l'utilisateur "userwp"
On peut lancer le conteneur:
podman start mymariadb
On verra le volume créé se remplir par les fichiers de la base de données MariaDb et le répertoire pour le schéma "dbwp".
On peut également visualiser le journal du conteneur:
podman logs mymariadb
Conteneur sur base de l'image "wordpress"
Le second projet consiste à installer un site Web basé sur WordPress. Un conteneur pour la base de données MariaDb vient d'être installé.
Nous avons mis notre dévolu sur l'image "docker.io/library/wordpress:latest". Le détail peut être consulté à l'URL: https://hub.docker.com/_/wordpress
On commence par créer un volume où on placera le contenu du site WordPress:
podman volume create htmlwp
En second, on crée un conteneur sur base de notre image "docker.io/library/wordpress".
podman create \ --name mywp \ --restart=always \ --hostname ctwp.home.dom \ --network podman:ip=10.88.0.12 \ --publish 127.0.0.1:8082:80 \ --env WORDPRESS_DB_HOST=192.168.1.66:3307 \ --env WORDPRESS_DB_NAME=dbwp \ --env WORDPRESS_DB_USER=userwp \ --env WORDPRESS_DB_PASSWORD=SuiteInconnue72 \ --volume htmlwp:/var/www/html \ docker.io/library/wordpress:latest
On a ajouté diverses options dont quelques-unes découlent de nos connaissances acquises aux points précédents:
- On nomme ce conteneur ("name"): "mywp".
- L'option "--restart=always" enclenche le démarrage automatique du conteneur lors du redémarrage de l'hôte comme vu plus tôt.
- On donne un nom de machine ("hostname") au conteneur plutôt qu'un nom aléatoire: "ctwp.home.dom".
- L'option "network" nous sert à imposer l'adresse IPv4 du conteneur à "10.88.0.12" sur base du réseau "podman" vu plus haut.
- On publie le port tcp/80 du service HTTPD du conteneur au niveau de l'hôte: "tcp/127.0.0.1:8082". On remarque que ce service ne sera accessible que par l'hôte en local. On verra plus loin l'intégration de plusieurs services Web, visibles par tous.
- Le contenu du site se trouve au niveau du conteneur dans le répertoire "/var/www/html". On va lier ce dossier au volume créé ci-dessus.
- Ensuite nous avons à notre disposition diverses variables d'environnement qui vont servir à créer la base de données et le schéma qui contiendra les données du site de WordPress.
- WORDPRESS_DB_NAME: pour le nom du schéma qui contiendra les données du site de WordPress
- WORDPRESS_DB_USER: pour le nom d'utilisateur ayant le droit d'accès au schéma "dbwp"
- WORDPRESS_DB_PASSWORD: pour le mot de passe de l'utilisateur "userwp"
- WORDPRESS_DB_HOST: pour l'adresse IP et le port pour accéder à la base de données. Il y a trois moyens d'accès:
- 10.88.0.13:3306: cette adresse correspond à celle du conteneur "mymariadb" qui écoute sur le port tcp/3306.
- 192.168.1.66:3307 et 10.88.0.1:3307: ces adresses correspondent à l'hôte qui a deux adresses IPv4, l'un vers notre réseau physique et l'autre vers le réseau des conteneurs. Il écoute lui par contre sur le port tcp/3307.
On peut lancer le conteneur:
podman start mywp
On verra le volume créé se remplir par les fichiers du site de WordPress. Quand on ajoutera des médias, on les verra apparaître dans le dossier "/var/lib/containers/storage/volumes/htmlwp/_data/wp-content/uploads".
On pourrait tester localement ce site:
lynx http://localhost:8082
Lors du premier démarrage, on demande la langue, le nom du site et un nom d'utilisateur et son mot de passe.
On peut également visualiser le journal du conteneur:
podman logs mywp
Note: Il est à remarquer qu'un conteneur ne peut interagir avec un autre conteneur que s'ils sont tous deux créés par le même utilisateur. C'est le cas des conteneurs "mywp" et "mymariadb".
Conteneur sur base de l'image "phpmyadmin"
Le troisième projet consiste à installer un site Web qui va gérer la base de données. Un conteneur pour la base de données MariaDb vient d'être installé. Le gestionnaire sera basé sur le logiciel bien connu "phpmyadmin".
Nous avons mis notre dévolu sur l'image "docker.io/library/phpmyadmin:latest". Le détail peut être consulté à l'URL: https://hub.docker.com/_/phpmyadmin
On crée un conteneur sur base de notre image "docker.io/library/phpmyadmin".
podman create \ --name myphpmyadmin \ --restart=always \ --hostname ctphpmyadmin.home.dom \ --network podman:ip=10.88.0.14 \ --publish 127.0.0.1:8083:80 \ --env PMA_HOST=192.168.1.66:3307 \ docker.io/library/phpmyadmin:latest
On a ajouté diverses options dont quelques-unes découlent de nos connaissances acquises aux points précédents:
- On nomme ce conteneur ("name"): "myphpmyadmin".
- L'option "--restart=always" enclenche le démarrage automatique du conteneur lors du redémarrage de l'hôte comme vu plus tôt.
- On donne un nom de machine ("hostname") au conteneur plutôt qu'un nom aléatoire: "ctphpmyadmin.home.dom".
- L'option "network" nous sert à imposer l'adresse IPv4 du conteneur à "10.88.0.14" sur base du réseau "podman" vu plus haut.
- On publie le port tcp/80 du service HTTPD du conteneur au niveau de l'hôte: "tcp/127.0.0.1:8083". On remarque que ce service ne sera accessible que par l'hôte en local. On verra plus loin l'intégration de plusieurs services Web, visibles par tous.
- Ensuite nous avons à notre disposition diverses variables d'environnement qui vont servir à définir le conteneur contenant la base de données.
- PMA_HOST: pour l'adresse IP et le port pour accéder à la base de données. Il y a trois moyens d'accès:
- 10.88.0.13:3306: cette adresse correspond à celle du conteneur "mymariadb" qui écoute sur le port tcp/3306.
- 192.168.1.66:3307 et 10.88.0.1:3307: ces adresses correspondent à l'hôte qui a deux adresses IPv4, l'un vers notre réseau physique et l'autre vers le réseau des conteneurs. Il écoute lui par contre sur le port tcp/3307.
- PMA_ARBITRARY: en alternative à la désignation d'un conteneur de base de données, on peut mettre cette variable à 1 (PMA_ARBITRARY=1) afin de pouvoir préciser librement l'adresse et le port du conteneur cible.
- PMA_HOST: pour l'adresse IP et le port pour accéder à la base de données. Il y a trois moyens d'accès:
Note: Pour s'authentifier, on utilise l'utilisateur de la base de données "root" dont on a défini le mot de passe lors de la création du conteneur "mymariadb" grâce à la variable d'environnement: "MARIADB_ROOT_PASSWORD".
On peut lancer le conteneur:
podman start myphpmyadmin
On pourrait tester localement ce site:
lynx http://localhost:8083
Lors du premier démarrage, on demande la langue, le nom du site et un nom d'utilisateur et son mot de passe.
On peut également visualiser le journal du conteneur:
podman logs myphpmyadmin
Note: Il est à remarquer qu'un conteneur ne peut interagir avec un autre conteneur que s'ils sont tous deux créés par le même utilisateur. C'est le cas des conteneurs "muphpmyadmin" et "mymariadb".
Conteneur sur base de l'image "portainer"
Une alternative à Cockpit qui est propre à RedHat, est l'utilisation d'un conteneur particulier qui présente les mêmes fonctionnalités et informations. Il se présente sous forme d'un interface Web. Nous avons mis notre dévolu sur l'image "portainer/portainer-ce:lts". Les instructions pour l'installation se trouvent sur le site du concepteur à l'URL: https://docs.portainer.io/start/install-ce/server/podman/linux
On commence par activer un service:
systemctl enable podman.socket systemctl start podman.socket
Ensuite il faut créer un volume où seront placés les paramètres:
podman volume create portainer_data
En troisième, on crée un conteneur sur base de notre image "portainer/portainer-ce:lts".
podman create \ --name portainer \ --restart=always \ --hostname ctportainer.home.dom \ --network podman:ip=10.88.0.15 \ --publish 127.0.0.1:9000:9000 \ --privileged \ --volume /run/podman/podman.sock:/var/run/docker.sock \ --volume portainer_data:/data \ docker.io/portainer/portainer-ce:lts \ --no-setup-token
On a ajouté diverses options dont quelques-unes découlent de notre connaissances acquises aux points précédents:
- On nomme ce conteneur ("name"): "myportainer".
- L'option "--restart=always" enclenche le démarrage automatique du conteneur lors du redémarrage de l'hôte comme vu plus tôt.
- On donne un nom de machine ("hostname") au conteneur plutôt qu'un nom aléatoire: "ctportainer.home.dom".
- L'option "network" nous sert à imposer l'adresse IPv4 du conteneur à "10.88.0.15" sur base du réseau "podman" vu plus haut.
- On publie le port tcp/9000 du service du conteneur au niveau de l'hôte: "tcp/127.0.0.1:9000". On remarque que ce service ne sera accessible que par l'hôte en local. On verra plus loin l'intégration de plusieurs services Web, visibles par tous.
- Les paramètres se trouvent au niveau du conteneur dans le répertoire "/data". On va lier ce dossier au volume créé ci-dessus. On lie aussi le socket enclenché.
- Lors de l'initialisation de l'authentification, il est normalement demandé un jeton que l'on trouve dans le journal du conteneur mais ce jeton a une durée de vie réduite et pour éviter son utilisation, on le désactive.
On peut lancer le conteneur:
podman start myportainer
Lors du premier contact avec cette application en mode Web, on demande de donner un mot de passe à l'utilisateur "admin" et de procurer un autre nom d'utilisateur en alternative.
Il est important de rappeler que Portainer comme Cockpit ne peuvent voir que les conteneurs créés sous un même utilisateur:
- Cockpit selon l'utilisateur authentifié, ne verra que les conteneurs créés par cet utilisateur;
- Portainer créé par un utilisateur ne verra que les conteneurs créés par ce même utilisateur.
Service HTTPD de l'hôte
Nous sommes en présence de trois services Web avec des ports différents: 9000, 8081 et 8082 mais qui ne sont accessibles que par l'hôte.
Pour les rassembler sous un même port tcp/80 classique, on va faire appel pour chacun à un nom de machine virtuelle et à une approche "proxy" et son inverse.
On crée un fichier "/etc/httpd/conf/proxy.conf" dont voici le contenu:
<VirtualHost *:80> ServerName asbl.home.dom ProxyRequests Off ProxyPass / http://127.0.0.1:8081/ ProxyPassReverse / http://127.0.0.1:8081/ ProxyPreserveHost On </VirtualHost> <VirtualHost *:80> ServerName wp.home.dom ProxyRequests Off ProxyPass / http://127.0.0.1:8082/ ProxyPassReverse / http://127.0.0.1:8082/ ProxyPreserveHost On <VirtualHost> <VirtualHost *:80> ServerName phpmyadmin.home.dom ProxyRequests Off ProxyPass / http://127.0.0.1:8083/ ProxyPassReverse / http://127.0.0.1:8083/ ProxyPreserveHost On <VirtualHost> <VirtualHost *:80> ServerName portainer.home.dom ProxyRequests Off ProxyPass / http://127.0.0.1:9000/ ProxyPassReverse / http://127.0.0.1:9000/ ProxyPreserveHost On </VirtualHost>
On ajoute en fin du fichier "/etc/httpd/conf/httpd.conf" l'appel à ce fichier:
... Include conf/proxy.conf
On relance le service HTTPD:
systemctl restart httpd.service
Cette configuration est basique et locales. On peut facilement l'adapter pour un accès Internet avec un cryptage via des certificats.
Ces trois noms de machines virtuelles sont soit ajoutés dans votre serveur DNS local, privé. A défaut, on ajoute leurs références dans le fichiers "hosts" des clients. Dans les machines Linux, il se trouve dans le répertoire "/etc" et sous MS Windows, "C:\windows\system32\drivers\etc".
Voici la ligne à ajouter dans notre cas dans le fichier "hosts":
192.168.1.66 portainer.home.dom wp.home.dom asbl.home.dom phpmyadmin.home.dom
Dès lors on peut y accéder via les URLs:
http://asbl.home.dom http://wp.home.dom http://phpmyadmin.home.dom http://portainer.home.dom
RootLess
Jusqu'à maintenant, nous avons travaillé sous l'utilisateur "root" qui a tous les droits. Pour une question de sécurité, il est conseillé de travailler sous un utilisateur classique ayant moins de droits. Mais dans cet environnement, il est nécessaire d'effectuer quelques adaptations.
Utilisateur
Nous allons ajouter un nouvel utilisateur que nous nommons "admincl":
adduser admincl
Cet utilisateur a dans notre cas l'UID de 1001 et le GID de 1001. Nous n'avons pas utilisé l'utilisateur ayant l'UID de 1000 et le GID de 1001 car avec ces ID, classiquement, c'est le premier utilisateur créé lors de l'installation du système qui peut accéder aux droits élevés via la commande "sudo".
Nous avons gardé son répertoire personne:: "/home/adminct"
Répertoires
La structure reprenant les images, volumes, conteneurs,... ont changés de place:
- Sous l'utilisateur "root", elle se trouve dans "/var/lib/containers/storage",
- Sous tout autre utilisateur, elle se trouve dans son espace: "~/.local/share/containers/storage" ou /home/adminct/.local/share/containers/storage" pour notre utilisateur "adminct".
Démarrage automatique des conteneurs
Nous sommes en présence d'un utilisateur classique et le démarrage automatique des conteneurs doit être déclenché de façon spécifique.
La commande suivante règle la première partie du problème:
systemctl --user enable podman-restart.service systemctl --user start podman-restart.service
Le script de lancement "podman-restart.service" ne se met pas dans le répertoire "/etc/systemd/system/default.target.wants" mais dans l'espace de l'utilisateur: "/home/adminct/.config/systemd/user/default.target.wants"
Le second problème à résoudre est le suivant. Si on active un conteneur est activé sous cet utilisateur, il démarre bien mais dès qu'on clôture la session de cet utilisateur, ce conteneur s'arrête. De même, un démarrage de l'hôte ne lance pas ce conteneur.
En fait, il faut avoir un privilège spécial que l'utilisateur "root" a. Il permet d'activer le "Systemd" de l'utilisateur perpétuellement.
Pour l'activer, on exécute la commande suivante:
loginctl enable-linger adminct
ou si on est sous la session de cet utilisateur:
loginctl enable-linger
Le fichier "/var/lib/systemd/linger/adminct" correspondant est créé.
Pour le désactiver, on utilise la commande inverse:
loginctl disable-linger adminct
Conteneurs
L'utilisation de la commande "podman" la même que sous l'utilisation sous l'utilisateur "root".
Nous avons rencontré deux cas liés:
- au conteneur "portainer" que nous allons traiter ci-dessous et
- à la gestion du réseau des conteneurs.
Le conteneur "portainer" fait appel à un socket activé par Systemd. Cette commande doit être adaptée au contexte de l'utilisateur classique:
systemctl --user enable podman-restart.service systemctl --user start podman-restart.service
En liaison, dans la commande de création de ce conteneur, le volume faisant référence à ce "socket" a changé de place vers: "/run/user/1001/podman/podman.sock:/var/run/docker.sock". On y remarque l'UID de notre utilisateur "adminct", à adaper selon l'utilisateur.
La commande devient:
podman create \ --name portainer \ --restart=always \ --hostname ctportainer.home.dom \ --network podman:ip=10.88.0.15 \ --publish 127.0.0.1:9000:9000 \ --privileged \ --volume /run/user/1001/podman/podman.sock:/var/run/docker.sock \ --volume portainer_data:/data \ docker.io/portainer/portainer-ce:lts \ --no-setup-token
Réseau PASTA
Lors de mon premier contact avec l'environnement d'un utilisateur classique, la gestion du réseau est fort différente.
En fait, un utilisateur classique ne peut créer ou gérer la couche réseau; il faut donc passer par quelques artifices. Les problèmes sont apparus suite à l'interaction en conteneurs; c'est le cas du conteneur "mywp" qui veut se connecter à la base de données du conteneur "mymariadb"; idem pour le conteneur "myphpmyadmin".
En première approche, je n'ai pas utilisé l'option "--network" dans la commande "podman create ...".
Dans ce cas, le système charge le processus "pasta" de régler ce problème.
Dans le conteneur qui est isolé du reste, l'adressage réseau de l'hôte est simplement recopiée dans celle du conteneur. Inévitablement tout administrateur réseau trouverait cela étrange et source de conflits. Si on se connecte dans ces conteneurs, on le visualise avec les commandes "ifconfig" ou "ip address".
Mais en correspondance, l'adresse IPv4 de l'hôte du côté du réseau des conteneurs prend la valeur "169.254.1.2" et le nom de machine "host.containers.internal". Or ce type d'adresse est de type "Local-Link". Elle se présente quand une machine ne disposant pas d'un adresse IPv4, en demande une à un serveur DHCP; s'il n'en obtient pas, il génère sa propre adresse de ce type. Elle a comme restriction d'être locale et non routable.
Pour résoudre ce problème qui se présente pour nos conteneurs "mywp" et "myphpmyadmin" voulant accéder au conteneur "mymariadb", on doit adapter les variables d'environnement:
- pour le conteneur "mywp", on met:
--env WORDPRESS_DB_HOST=host.containers.internal:3307 \
ou
--env WORDPRESS_DB_HOST=169.254.1.2:3307 \
- pour le conteneur "myphpmyadmin", on met:
--env PMA_HOST=host.containers.internal:3307 \
ou
--env PMA_HOST=169.254.1.2:3307 \
Si on se connecte dans ces conteneurs, on retrouve cette déclarative dans le fichier "/etc/hosts".
Réseau PODMAN
Pour résoudre ce problème, on fait appel au réseau "podman" ou à tout autre réseau créé via la commande "podman network create ...".
A toute création de tout nouveau conteneur, on fait appel à l'option "network" en spécifiant le nom du réseau à utiliser, par exemple:
--network podman
et on se retrouve dans la situation de l'utilisateur "root" pour la couche réseau.
Mais elle devient une pseudo-couche réseau. Il faut utiliser une commande spéciale au niveau de l'hôte pour la visualiser, par exemple:
- pour l'adressage IP, on lance la commande:
podman unshare --rootless-netns ip address
au lieu de:
ip address
- pour la table de routage, on lance la commande:
podman unshare --rootless-netns ip route
au lieu de:
ip route
Par exemple, si on lance seul le conteneur "myasbl", on a pour l'adressage:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host proto kernel_lo
valid_lft forever preferred_lft forever
2: enp0s25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether f2:4e:6b:f0:ae:93 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.66/24 brd 192.168.1.255 scope global noprefixroute enp0s25
valid_lft forever preferred_lft forever
inet6 fe80::f04e:6bff:fef0:ae93/64 scope link nodad proto kernel_ll
valid_lft forever preferred_lft forever
3: podman0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc noqueue state UP group default qlen 1000
link/ether 0e:b2:40:0b:a0:34 brd ff:ff:ff:ff:ff:ff
inet 10.88.0.1/16 brd 10.88.255.255 scope global podman0
valid_lft forever preferred_lft forever
inet6 fe80::cb2:40ff:fe0b:a034/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
4: veth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc noqueue master podman0 state UP group default qlen 1000
link/ether 86:ed:1d:90:7b:df brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::84ed:1dff:fe90:7bdf/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
et pour la table de routage:
default via 192.168.1.1 dev enp0s25 proto static metric 100 10.88.0.0/16 dev podman0 proto kernel scope link src 10.88.0.1 192.168.1.0/24 dev enp0s25 proto kernel scope link metric 100
En conclusion, on garde les commandes de création de conteneurs identiques à celles utilisées pour l'utilisateur "root" et nos problèmes d'interconnexions entre conteneurs sont résolus et on évite de processus "pasta".