Tu as un modèle Ubuntu Server qui te donne une VM propre en dix secondes. La dernière fois , on s’est quittés sur une question : qu’est-ce qu’on fait tourner dessus ?

Le réflexe, c’est d’installer chaque service directement sur la machine. Un serveur de fichiers, un gestionnaire de photos, un outil de monitoring. Chacun apporte ses dépendances, ses versions de bibliothèques, ses fichiers de configuration éparpillés. Six mois plus tard, tu mets à jour l’un et tu casses l’autre. Et le jour où tu veux déménager un service sur une autre machine, tu ne sais plus ce qu’il a déposé où.

Docker règle ça en emballant chaque service avec tout ce dont il a besoin, dans une boîte isolée du reste. Le service tourne pareil partout. Tu le supprimes, il ne laisse rien derrière lui. Tu le déplaces, tu emportes la boîte. Et comme chaque boîte reste dans sa bulle, une seule machine peut en faire tourner des dizaines, côte à côte, sans qu’elles se marchent dessus. C’est pour ça que la quasi-totalité des logiciels auto-hébergeables te proposent aujourd’hui une installation par Docker en premier.

Mais Docker n’est pas neutre, et on va le regarder en face. Derrière, il y a Docker Inc, une entreprise. Son moteur est libre, mais les images que tu vas télécharger viennent d’un catalogue en ligne qu’elle contrôle. Et installer Docker, c’est installer un service qui tourne avec les pleins pouvoirs sur ta machine. Tous tes conteneurs partagent ce moteur, la même mémoire et le même disque : ce qui est très exposé ou très sensible méritera parfois sa propre VM. Mal compris, Docker est une porte ouverte. Bien compris, c’est un outil qui te rend autonome.

Dans cet article, on part d’un clone de ton modèle et on va :

  • préparer la VM, en commençant par un piège de disque que ton modèle t’a laissé ;
  • installer Docker depuis le dépôt officiel, pas depuis un script tout fait ;
  • comprendre ce que tu donnes vraiment en ajoutant ton compte au groupe docker ;
  • manipuler les quatre briques de Docker : image, conteneur, volume, réseau ;
  • publier un service sans l’exposer à tout ton réseau.

À la fin, tu ne sauras pas seulement lancer un conteneur. Tu sauras ce qu’il fait sur ta machine, et ce qu’il ne doit pas faire.

Environnement de ce tuto : Ubuntu Server 26.04.1, cloné depuis le modèle de l’article précédent , en VM sur Proxmox VE 9.2.21, dans un réseau de démonstration. Docker Engine 29.8.1. Toutes les manipulations ont été testées sur cet environnement le 30 septembre 2026.

1. Préparer la VM

Pourquoi une VM, et pas un conteneur LXC

Si tu as lu VM ou LXC , la question te brûle les lèvres : Docker fabrique des conteneurs, Proxmox en fabrique aussi, pourquoi ne pas mettre Docker dans un LXC, plus léger ?

Parce qu’on empilerait deux couches de conteneurs qui partagent toutes les deux le noyau de ton hôte Proxmox. Et le moteur Docker tourne avec les pleins pouvoirs. Dans un LXC, une faille dans un conteneur Docker n’est séparée de ton hyperviseur que par des cloisons fines. Dans une VM, elle se heurte à un noyau complet, le sien, qui n’est pas celui de Proxmox.

Ce n’est pas qu’une précaution de ma part. La documentation de Proxmox elle-même recommande de faire tourner les conteneurs applicatifs dans une VM quand on veut une isolation maximale. Elle précise aussi que Docker dans un LXC non privilégié réclame une option spéciale, qui entre en conflit avec la gestion réseau de systemd. Ça marche, beaucoup le font, mais tu choisis la voie qui demande des rustines.

On paie la VM en mémoire. En échange, on gagne une frontière nette entre tes services et ton hyperviseur. Sur un homelab qui te sert tous les jours, c’est le bon échange.

Cloner le modèle

Clic droit sur ton modèle Ubuntu-serveur-template, Clone.

Interface Proxmox VE, clic droit sur le modèle Ubuntu-serveur-template avec l'option Clone en surbrillance

Cette fois, prends Full Clone.

On l’a vu dans l’article précédent : le clone lié est parfait pour du jetable, mais il dépend du modèle à vie. Une machine Docker, tu vas y installer des services que tu gardes. Elle doit pouvoir vivre sans son modèle, même le jour où tu le recrées.

Donne-lui un nom sans point, ici docker-demo.

Fenêtre Clone VM Template de Proxmox, nom docker-demo et mode Full Clone sélectionné

Avant de démarrer, onglet Cloud-Init du clone, IP Config : une adresse fixe dans ta zone, avec sa passerelle. Un serveur qui héberge des services doit toujours se trouver à la même adresse.

Onglet Cloud-Init de la VM docker-demo dans Proxmox, avec l'utilisateur admin, la clé SSH et la ligne IP Config sélectionnée
Fenêtre Edit Network Config de Proxmox, IPv4 en statique avec une adresse fixe et sa passerelle

Démarre. Au premier boot, Cloud-Init crée ton compte, pose ta clé, puis applique les mises à jour disponibles. Laisse-lui une ou deux minutes avant de lancer la moindre commande apt : tant qu’il travaille, le gestionnaire de paquets est verrouillé, et ta commande échouera avec un message de verrou qui n’a rien d’alarmant.

Connecte-toi :

ssh admin@<adresse-de-ta-vm>

Récupérer l’espace que ton modèle t’a laissé

Souviens-toi de l’installation d’Ubuntu : sur un disque de 32 Go, l’installateur n’a donné qu’environ 15 Go à la racine et gardé le reste en réserve dans le groupe LVM. Pour une VM de test, ça passe. Pour Docker, non.

Docker range tout au même endroit, sous /var/lib/docker : les images que tu télécharges, les conteneurs, les volumes où vivent tes données, et leurs journaux. Tout ça atterrit sur la racine. Quelques images de services courants, et tes 15 Go fondent. Un disque plein, c’est un serveur qui cesse de répondre, souvent au pire moment.

Vérifie d’abord ce que tu as :

df -h /
sudo vgs

La première commande montre la taille de ta racine. La seconde montre le groupe de volumes ubuntu-vg, avec l’espace encore libre dans la colonne VFree.

Terminal, df -h montre une racine de 15 Go et sudo vgs montre 15 Go libres dans le groupe ubuntu-vg

On donne tout cet espace libre à la racine, en une commande :

sudo lvextend -r -l +100%FREE /dev/ubuntu-vg/ubuntu-lv

-l +100%FREE prend tout l’espace libre du groupe. -r agrandit dans la foulée le système de fichiers, sinon le volume grandirait sans que la racine le voie. L’opération se fait à chaud, sans redémarrer.

Terminal, la commande lvextend agrandit le volume de 15 à 30 Go puis redimensionne le système de fichiers ext4 à chaud

Relance df -h / : ta racine occupe maintenant presque tout le disque.

Terminal, df -h montre désormais une racine de 30 Go et VFree est à zéro

Et si 32 Go ne suffisent pas ? Pour apprendre et faire tourner quelques services, c’est large. Le jour où tu veux plus, on agrandit d’abord le disque dans Proxmox, puis la partition, puis le volume. C’est une manipulation à part, qu’on ne fait pas ici.

2. Installer Docker depuis le dépôt officiel

Trois façons d’installer Docker, une seule qu’on garde

Tu vas croiser trois méthodes dans les tutos.

Le paquet d’Ubuntu. Un simple apt install docker.io. La documentation de Docker range ce paquet parmi les versions non officielles, distribuées par ta distribution et non par Docker, et demande de le retirer avant d’installer la version officielle.

Le script tout fait. Une ligne qui télécharge un script et l’exécute avec les droits administrateur. C’est rapide, et c’est exactement ce qu’on évite. Docker lui-même le réserve aux environnements de test et de développement : il installe des paquets sans demander de confirmation, et peut te faire changer de version majeure sans prévenir. Exécuter en administrateur un script qu’on n’a pas lu, c’est confier les clés de sa machine sans regarder à qui.

Le dépôt officiel de Docker. On déclare à apt une nouvelle source de paquets, signée par Docker. Ensuite, Docker s’installe et se met à jour comme n’importe quel logiciel du système, avec le même apt upgrade que le reste. C’est la méthode qu’on garde.

Une honnêteté avant d’y aller : ajouter ce dépôt, c’est faire confiance à Docker Inc pour livrer des paquets qui tourneront en administrateur sur ta machine. C’est le prix de toute installation logicielle. La différence, c’est que tu sais maintenant qui tu crois, et comment le vérifier.

Si tu installes sur une machine existante. Sur un clone neuf de ton modèle, il n’y a rien à nettoyer. Sur une machine plus ancienne, une installation précédente de Docker peut traîner. La documentation officielle demande de la retirer d’abord avec la commande ci-dessous. Si rien n’est installé, apt te le dira et tu passes à la suite.

sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc | cut -f1)

Déclarer le dépôt de Docker

D’abord, la clé de signature :

sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

Cette clé est ce qui permet à apt de vérifier que chaque paquet vient bien de Docker et n’a pas été modifié en route. Même logique que l’empreinte de l’image Ubuntu dans l’article précédent : on ne fait pas confiance au transport, on vérifie le contenu.

Terminal, mise à jour des paquets puis téléchargement de la clé de signature de Docker dans /etc/apt/keyrings

Ensuite, la source elle-même :

sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

Deux lignes méritent un mot. Suites lit le nom de code de ton Ubuntu directement dans le système : sur la 26.04, il écrira resolute, sans que tu aies à le taper. Signed-By lie cette clé à ce seul dépôt : elle ne pourra pas servir à valider des paquets venus d’ailleurs.

Terminal, création du fichier docker.sources, la ligne Suites est remplie automatiquement avec resolute

Vérifie ce qui a été écrit, puis rafraîchis la liste des paquets :

cat /etc/apt/sources.list.d/docker.sources
sudo apt update

La ligne Suites doit afficher resolute, et apt update doit lister le dépôt download.docker.com sans erreur de signature.

Terminal, contenu du fichier docker.sources puis apt update qui récupère le dépôt download.docker.com sans erreur

Installer les paquets

sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Cinq paquets demandés, et chacun a son rôle :

PaquetCe qu’il fait
docker-ceLe moteur, le service qui fait tourner les conteneurs
docker-ce-cliLa commande docker que tu tapes
containerd.ioLa couche qui gère réellement les conteneurs sous le moteur
docker-buildx-pluginPour fabriquer tes propres images
docker-compose-pluginPour décrire plusieurs conteneurs dans un fichier, on s’en servira dans le prochain article

apt t’annonce en fait sept paquets : il ajoute tout seul deux dépendances, docker-ce-rootless-extras et pigz. C’est normal.

Terminal, apt install des cinq paquets Docker, avec deux dépendances ajoutées automatiquement, sept paquets au total

Sur Ubuntu, le service démarre tout seul à l’installation et à chaque démarrage de la machine. Vérifie :

sudo systemctl status docker

Tu dois lire active (running).

Terminal, sudo systemctl status docker affiche le service actif et activé au démarrage

Note au passage la version installée :

docker --version
Terminal, docker --version affiche Docker version 29.8.1

Le premier conteneur

Le test que propose Docker :

sudo docker run hello-world

Ce qui se passe mérite qu’on le déroule. Docker cherche l’image hello-world sur ta machine, ne la trouve pas, la télécharge depuis le Docker Hub, le catalogue public de Docker, puis lance un conteneur à partir de cette image. Le conteneur affiche un message de bienvenue et s’arrête.

Terminal, sudo docker run hello-world télécharge l'image depuis le Docker Hub puis affiche Hello from Docker

C’est ton premier contact avec le catalogue, et il s’est fait sans que tu le demandes explicitement. Retiens ce réflexe de Docker : quand une image manque, il va la chercher. On en reparle dans la section sur les images.

Tu remarques le sudo devant chaque commande. Sans lui, Docker refuse. La section suivante explique pourquoi, et ce que ça coûte de s’en passer.

3. Le groupe docker : ce que tu donnes vraiment

Pourquoi Docker exige sudo

La commande docker que tu tapes n’est qu’une télécommande. Le vrai travail, c’est le moteur qui le fait, un service qui tourne en permanence en arrière-plan. Les deux se parlent par un fichier spécial, un socket, qui appartient à l’administrateur système. Sans sudo, ta télécommande n’a pas le droit de toucher ce socket. D’où le refus.

Et ce moteur tourne toujours en administrateur. Ce n’est pas un réglage, c’est sa nature : pour isoler des conteneurs, il doit manipuler le noyau, le réseau, les disques.

Pourquoi c’est une question de sécurité, pas de confort

Tous les tutos te font taper la même chose : ajouter ton compte au groupe docker, et ne plus jamais écrire sudo. Présenté comme un confort. C’est plus que ça.

La documentation de Docker le dit sans détour : le groupe docker donne des privilèges équivalents à ceux de l’administrateur. Et elle explique pourquoi. Docker permet de partager un dossier de ta machine avec un conteneur, sans limiter ce que le conteneur peut en faire. Rien n’empêche de lui donner la racine / entière. Quiconque peut piloter Docker peut donc lancer un conteneur qui lit et modifie n’importe quel fichier de ton système, mots de passe compris.

Autrement dit : un membre du groupe docker est administrateur, sans qu’on lui demande jamais de le prouver.

Ce qu’on choisit ici, et pourquoi

Ton compte admin a déjà les droits administrateur, par sudo. L’ajouter au groupe docker ne lui donne donc pas de pouvoir nouveau. Ce que tu perds, c’est une barrière : sans sudo, n’importe quel programme lancé sous ton compte peut parler à Docker, donc devenir administrateur. La documentation le formule ainsi : l’appartenance permanente au groupe donne accès au socket à tous les processus de ta session.

Sur une VM dédiée à Docker, où tu es seul à te connecter, par clé, c’est un échange raisonnable. On le fait, en le sachant.

Deux règles pour que ce choix reste sain :

  • Un seul compte dans ce groupe : le tien. Jamais un compte de service, jamais un compte partagé.
  • Pas de membre du groupe docker sur une machine où tu n’as pas confiance dans tout ce qui tourne sous ce compte.

Ajouter ton compte au groupe

Sur Ubuntu, l’installation a déjà créé le groupe. Il suffit d’y ajouter ton compte :

sudo usermod -aG docker $USER

Décortiquée :

  • sudo : on agit en administrateur, obligatoire pour modifier les groupes.
  • usermod : la commande qui modifie un compte utilisateur.
  • -aG docker : G veut dire « groupe », ici le groupe docker, et a veut dire « ajouter ».
  • $USER : ton nom de compte, rempli automatiquement.

N’oublie surtout pas le a. Sans lui, la commande ne rajoute pas le groupe : elle remplace tous tes groupes par docker. Ton compte perdrait sudo, donc tes droits d’administrateur.

L’appartenance à un groupe n’est lue qu’à la connexion. Déconnecte-toi avec exit, puis reconnecte-toi en SSH.

Terminal, ajout du compte au groupe docker avec usermod, puis déconnexion et reconnexion en SSH

Vérifie :

groups

docker doit apparaître dans la liste, et sudo doit toujours y être. Puis le test, cette fois sans sudo :

docker run hello-world
Terminal, groups liste sudo et docker, puis docker run hello-world fonctionne sans sudo

Si tu vois « permission denied » sur config.json. Tu as lancé Docker avec sudo avant de rejoindre le groupe, et un dossier ~/.docker a été créé au nom de l’administrateur. La documentation propose de rendre ce dossier à ton compte avec les deux commandes ci-dessous.

sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
sudo chmod g+rwx "$HOME/.docker" -R

Il existe plus strict

Docker propose un mode sans administrateur, dit rootless, où le moteur lui-même tourne sous ton compte. Il ferme la porte qu’on vient d’ouvrir, au prix d’une installation différente et de limitations propres. C’est un sujet à part entière, qu’on ne traite pas ici. Retiens qu’il existe, et que le choix qu’on a fait n’est pas le seul possible.

4. Les quatre briques de Docker

Dans Docker, quatre mots reviennent tout le temps. Une fois que tu les as compris, tous les tutos deviennent clairs.

MotEn clairPour t’en souvenir
ImageLe modèle d’un service, qui ne bouge pasLe moule
ConteneurLe service qui tourne, fabriqué depuis l’imageLe gâteau
VolumeUn espace où tes données sont à l’abriLe coffre
RéseauCe qui permet aux conteneurs de se parlerLe couloir

Tu connais déjà cette logique : c’est celle de ton modèle Proxmox et de ses clones. On va essayer chaque brique avec un vrai serveur web, nginx.

L’image : le moule

Télécharge l’image de nginx, puis affiche les images présentes sur ta machine :

docker pull nginx
docker image ls

C’est tout. Tu as un moule, prêt à servir.

Un conseil dès maintenant : préfère toujours les images officielles, comme nginx. Une image publiée par un inconnu peut contenir n’importe quoi, et elle tournera chez toi.

Le conteneur : jetable

Fabrique un conteneur à partir du moule :

docker run -d --name web nginx
docker ps

--name web donne au conteneur le nom web. --name est l’option, web est le nom : tu peux en choisir un autre, en lettres sans accent, chiffres ou tirets, sans espace. On s’en sert dans toutes les commandes suivantes pour désigner ce conteneur, donc si tu le changes, change-le partout. -d le fait tourner en arrière-plan. docker ps te montre qu’il est bien là.

« The container name “/web” is already in use » ? Un conteneur nommé web existe déjà, souvent un reste d’essai. Supprime-le avec docker rm -f web : rm supprime le conteneur, -f force même s’il tourne encore. Seul le conteneur disparaît, l’image reste. Puis relance ta commande.

Maintenant, un petit test. Écris une phrase dans le conteneur, puis relis-la :

docker exec web sh -c 'echo "Bonjour depuis HMT" > /usr/share/nginx/html/index.html'
docker exec web cat /usr/share/nginx/html/index.html

Ta phrase s’affiche. Supprime le conteneur, recrée-le, et relis :

docker rm -f web
docker run -d --name web nginx
docker exec web cat /usr/share/nginx/html/index.html

Ta phrase a disparu. À la place, tu vois s’afficher un long bloc de code en anglais, avec Welcome to nginx! dans le titre : c’est la page par défaut de nginx, celle du moule d’origine. Tout ce qui est écrit dans un conteneur disparaît avec lui.

Terminal, après suppression et recréation du conteneur web, la phrase a disparu et la page par défaut Welcome to nginx s'affiche

C’est voulu. Un conteneur, on le jette et on le refait sans regret, par exemple pour une mise à jour. Tes données, elles, doivent être rangées ailleurs. C’est le rôle du volume.

Le volume : le coffre

Crée un coffre nommé site, et branche-le au conteneur, à l’endroit où nginx range ses pages :

docker rm -f web
docker volume create site
docker run -d --name web --mount source=site,target=/usr/share/nginx/html nginx

Tu croiseras souvent -v à la place de --mount. Les deux font la même chose, --mount est juste plus lisible.

Refais le même test qu’avant :

docker exec web sh -c 'echo "Bonjour depuis HMT" > /usr/share/nginx/html/index.html'
docker rm -f web
docker run -d --name web --mount source=site,target=/usr/share/nginx/html nginx
docker exec web cat /usr/share/nginx/html/index.html

Cette fois, ta phrase est toujours là. Le conteneur est neuf, mais tes données ont survécu dans le coffre.

Ce coffre existe vraiment sur ton disque :

sudo ls /var/lib/docker/volumes/site/_data

Il est sur ta racine. C’est pour ça qu’on l’a agrandie en section 1.

Terminal, la phrase Bonjour depuis HMT survit à la recréation du conteneur, puis le dossier du volume site apparaît sur le disque et docker volume ls le liste

Un coffre ne se vide jamais tout seul. Supprimer un conteneur ne supprime pas son volume. C’est ce qui protège tes données. Mais les volumes oubliés s’accumulent et remplissent ton disque. docker volume ls te montre ceux qui traînent.

Le réseau : le couloir

Lance un deuxième petit conteneur, alpine, et demande-lui d’aller voir la page de web :

docker run --rm alpine wget -qO- http://web

--rm le supprime dès qu’il a fini. Résultat : échec. Le message exact dépend de ton réseau : chez moi, wget répond Connection refused vers une adresse sans rapport. Ce qui compte, c’est que alpine n’a pas trouvé ta page.

Terminal, le conteneur alpine télécharge son image puis échoue à joindre le conteneur web par son nom

Par défaut, les conteneurs ne se connaissent pas par leur nom. Pour ça, il faut leur créer un couloir commun, un réseau à toi :

docker network create hmt-net
docker rm -f web
docker run -d --name web --network hmt-net --mount source=site,target=/usr/share/nginx/html nginx
docker run --rm --network hmt-net alpine wget -qO- http://web

Cette fois, alpine trouve web et affiche ta phrase.

Terminal, sur le réseau hmt-net, alpine joint le conteneur web par son nom et affiche Bonjour depuis HMT

Ce couloir sert aussi de cloison : seuls les conteneurs qui y sont branchés se voient. Tu retrouves la logique de tes VLAN : on relie seulement ce qui doit se parler.

Où on en est

Ton serveur web tourne, tes données sont à l’abri, tes conteneurs se parlent. Il manque une chose : personne en dehors de la VM ne peut voir ta page. C’est la prochaine étape.

5. Ouvrir ton service, mais pas à n’importe qui

Ta VM est une maison

Pour l’instant, ton serveur web tourne à l’intérieur de la VM. Il est comme une pièce sans porte : il fonctionne, mais personne dehors ne peut y entrer. Pas même ton PC.

Pour le rendre visible, il faut percer une porte. Dans Docker, on dit publier un port.

docker rm -f web
docker run -d --name web --network hmt-net --mount source=site,target=/usr/share/nginx/html -p 8080:80 nginx
docker ps

La nouveauté, c’est -p 8080:80. Traduction : « quand quelqu’un frappe à la porte 8080 de la VM, envoie-le vers nginx ».

Ouvre ton navigateur sur http://<adresse-de-ta-vm>:8080. Ta phrase s’affiche. Ton service est en ligne.

Navigateur du poste de travail sur l'adresse de la VM au port 8080, la page affiche Bonjour depuis HMT

Attention : cette porte donne sur la rue

Regarde la colonne PORTS de docker ps. Tu y vois 0.0.0.0:8080->80/tcp, puis [::]:8080->80/tcp, la même chose en IPv6.

Terminal, docker ps montre le conteneur web publié sur 0.0.0.0:8080 et [::]:8080, c'est-à-dire sur toutes les adresses de la VM

Ces adresses veulent dire « toutes les adresses de la machine » : par défaut, Docker ouvre la porte à tout le monde. N’importe quel appareil qui peut joindre ta VM peut entrer. La documentation de Docker le reconnaît elle-même : ouvrir un port, c’est l’ouvrir au monde extérieur.

Et il y a un piège. Ubuntu a un pare-feu intégré, ufw. Beaucoup s’en servent pour fermer les portes d’un serveur. Avec Docker, il ne marche pas : Docker ouvre ses portes en passant à côté. Tu peux bloquer un port dans ufw, Docker le laissera ouvert quand même. C’est l’erreur la plus fréquente, et rien ne te prévient.

Bonne nouvelle : une porte que tu n’ouvres pas reste fermée. Le danger vient seulement de ce que tu ouvres toi-même.

Chez toi, il y a un gardien

Ta VM n’est pas seule dans la rue. Elle est derrière ton pare-feu OPNsense , qui décide qui peut s’approcher de la maison. Ta caméra connectée, par exemple, n’a rien à faire là.

Mais le gardien ne surveille que l’entrée du quartier. À l’intérieur d’une même zone de ton réseau, tous les voisins peuvent frapper à ta porte.

Une porte qui ne donne que sur l’intérieur

Parfois, personne dehors n’a besoin d’entrer. Alors on perce une porte qui ne donne que sur l’intérieur de la maison :

docker rm -f web
docker run -d --name web --network hmt-net --mount source=site,target=/usr/share/nginx/html -p 127.0.0.1:8080:80 nginx

On a juste ajouté 127.0.0.1 devant. C’est l’adresse qui veut dire « moi-même ». La VM peut entrer, personne d’autre.

Terminal, recréation du conteneur web avec le port 8080 publié uniquement sur 127.0.0.1

Vérifie depuis la VM :

curl http://127.0.0.1:8080
Terminal, curl sur 127.0.0.1 port 8080 depuis la VM affiche Bonjour depuis HMT

Ta phrase s’affiche. Maintenant, recharge la page dans le navigateur de ton PC : la connexion échoue.

Navigateur du poste de travail sur l'adresse de la VM au port 8080, Firefox affiche La connexion a échoué

Le service tourne toujours, mais sa porte ne donne plus sur la rue.

La règle à garder en tête

N’ouvre que les portes nécessaires, et le moins largement possible.

Tes conteneurs n’ont pas besoin de portes pour se parler entre eux : ils passent par leur réseau Docker, comme alpine a trouvé web tout à l’heure. Une base de données, par exemple, ne devrait jamais avoir de porte sur la rue.

Vérifie ta version. Sur les versions de Docker antérieures à la 28.0.0, la porte « intérieure » laissait passer les voisins proches. Tape docker --version : depuis le dépôt officiel, tu es à jour.

Ce que tu sais faire maintenant

Prends une seconde pour regarder ce qui tourne sur ta VM. Il y a une heure, c’était un clone vide. Maintenant, c’est un serveur qui héberge ton premier service, et que tu comprends de bout en bout. Ce n’est pas rien.

Tu as fait le chemin complet. Tu sais pourquoi Docker a sa place dans une VM. Tu l’as installé depuis sa vraie source, pas depuis un script avalé les yeux fermés. Tu sais ce que tu donnes en rejoignant le groupe docker. Tu as joué avec les quatre briques : l’image qui sert de moule, le conteneur qu’on jette sans regret, le volume qui garde tes données au chaud, le réseau qui relie ce qui doit l’être. Et tu sais ouvrir une porte vers ton service sans l’ouvrir sur la rue.

Maintenant, amuse-toi. Lance d’autres images, casse des conteneurs, recrée-les. Tu ne risques rien : c’est fait pour ça. Et si un jour tout part de travers, ton modèle te redonne une VM neuve en dix secondes. C’est comme ça qu’on apprend vraiment.

Garde juste un œil ouvert, comme on l’a fait tout au long de l’article. Des images officielles plutôt que celles d’inconnus. Seulement les portes nécessaires. Et ta VM bien au chaud derrière ton pare-feu. La souveraineté, ce n’est pas refuser les outils. C’est savoir ce qu’ils font, et c’est exactement ce que tu sais maintenant.

Il reste une étape pour que ce soit vraiment confortable. Jusqu’ici, on a tout tapé à la main, une commande après l’autre. Parfait pour comprendre, mais vite pénible quand plusieurs conteneurs doivent travailler ensemble. La prochaine fois, on écrira tout ça dans un simple fichier, et un service entier se lancera en une seule commande. C’est le rôle de Docker Compose, et on s’y met ensemble.

À très vite.

Ta tech, tes règles, ta liberté.

Sources