Pendant longtemps, j’ai tout hébergé sur un simple VPS : un système unique où cohabitaient mes services web, mes bases de données et mes outils de développement. Avec l’arrivée de mon homelab et l’essor de la conteneurisation, j’ai dû repenser mon approche. Les container m’ont permis d’automatiser, de segmenter et de déployer plus rapidement. Mais cette évolution soulève une question plus large : peut-on vraiment tout mettre en conteneur ? Faut-il abandonner les machines virtuelles, ou conserver une approche hybride selon les objectifs, notamment en matière de sécurité, de réseau et d’orchestration ? C’est cette interrogation qui guide ma réflexion aujourd’hui.
Qu’est-ce que la conteneurisation ?
La conteneurisation consiste à regrouper le code d’une application avec toutes ses dépendances (librairies, frameworks, configs…) dans un « conteneur » isolé voir site RedHat . Cette capsule logicielle est indépendante de l’infrastructure sous-jacente, garantissant qu’une app s’exécute de la même façon dans les envrionnements de dev, de test ou de prod. Contrairement à la virtualisation classique sur VM, qui émule un hardware complet avec un OS invité, un conteneur ne virtualise que l’environnement applicatif. Comme le note Docker, « les conteneurs sont une abstraction au niveau applicatif qui empaquette le code et ses dépendances, partageant le noyau du système », tandis que « les machines virtuelles sont une abstraction du hardware, chaque VM ayant son propre système d’exploitation ». En pratique, cela signifie qu’une VM inclut un système complet (noyau, pilotes…) mesurant plusieurs giga et nécessitant un démarrage plus lent, alors qu’un conteneur pèse souvent quelques mega (selon l'image choisie) et s’appuie sur le noyau de l’hôte. Un seul serveur peut ainsi faire tourner des dizaines, voire des centaines de conteneurs où il ne supporterait que quelques VMs équivalentes.
En termes de schéma, on peut dire que les conteneurs constituent une couche légère au‑dessus du système d’exploitation hôte. Ils partagent ce noyau (Linux) mais isolent l’application au niveau processus, grâce à des namespaces et cgroups du noyau. De fait, on peut lancer des applications dans des conteneurs de manière très rapide et répétable : le même conteneur se comporte de la même façon sur mon serveur, sur un cloud ou sur mon laptop. Cette portabilité est un grand atout pour gérer un homelab très hétérogène.
Avantages clés des containers
La conteneurisation apporte plusieurs bénéfices concrets pour le développement et l’exploitation des applications :
- Portabilité et cohérence : comme déjà dit, un conteneur fonctionne de la même façon partout (développement, test, production), ce qui élimine les bugs dus à des environnements différents. On peut ainsi construire une image Docker/Podman une fois et l’exécuter sur n’importe quelle machine compatible.
- Efficacité des ressources : les conteneurs sont légers et rapides, car ils partagent le noyau de l’hôte. Ils consomment beaucoup moins qu’une VM traditionnelle, permettant de faire tourner bien plus d’applications sur le même serveur.
- Démarrage ultra-rapide : la création, l’arrêt ou la suppression d’un conteneur se fait en quelques secondes seulement, idéal pour des processus CI/CD ou des architectures microservices.
- Isolation applicative : chaque conteneur tourne dans son espace cloisonné (avec son namespace de processus, réseau, etc.). En cas de faille dans une app, l’impact reste limité au conteneur concerné.
- Scalabilité dynamique : on peut ajuster à la volée le nombre de conteneurs d’un service selon la charge (auto-scaling). Cette souplesse est précieuse pour absorber les pics de trafic.
- Facilité de développement et tests : l’environnement (librairies, versions) est encapsulé avec l’app. Finie l’excuse du genre « ça marche chez moi, mais pas en prod ». On peut reproduire localement exactement la même configuration qu’en production.
Concrètement, on trouve pour quasiment chaque service la possibilité d’un conteneur officiel ou communautaire : Nextcloud, Gitea, Keycloak, Grafana, VaultWarden, SonarQube… autant d’apps prêtes à l’emploi en OCI (Docker/Podman). Ceci accélère fortement les déploiements et les mises à jour (on détruit l’ancien conteneur et on en lance un nouveau), simplifiant l’administration.
Limites et questions de sécurité
Pour autant, le tout-containers n’est pas dépourvu de limites, notamment en matière de sécurité. D’abord, un conteneur partage le noyau de l’hôte, ce qui crée un point de confiance critique. Si un attaquant réussit à s’échapper d’un conteneur (via une faille du noyau ou une mauvaise configuration), il peut compromettre l’hôte tout entier. C’est pourquoi Proxmox VE recommande par exemple d’exécuter les conteneurs Docker à l’intérieur d’une VM pour bénéficier d’une isolation forte de l’hôte et de fonctionnalités avancées (migration à chaud, snapshots…) impossible en conteneur pur.
De plus, les LXC (les containers système de Proxmox) et les conteneurs Docker/Podman (containers applicatifs) n’ont pas du tout la même philosophie. Comme l’explique un contributeur du forum Proxmox : les LXC contiennent un OS complet (sauf noyau) et se gèrent comme des VMs, tandis que les Docker ne contiennent qu’une seule application jetable. En clair : pour un service hautement critique ou nécessitant un OS spécial (Windows, BSD), une VM reste préférable. Pour un service Linux moins sensible où on veut minimiser l’empreinte, un LXC est envisageable, au prix d’un peu moins de sécurisation. Et pour des services simples où l’on ne veut pas se prendre la tête, on peut lancer un conteneur (Docker/Podman) depuis une VM dédiée.
En pratique : je privilégie les VM pour les services qui nécessitent une forte isolation ou un OS propriétaire (par exemple, un serveur Windows ou un bastion critique). Les applications GNU/Linux classiques (Nextcloud, Grafana…) peuvent fonctionner en conteneurs. Mais il faut rester vigilant : ne pas dérouler un service web sensible en tant que conteneur root exposé directement sur Internet. Il faut appliquer les bonnes pratiques (minimiser l’image, limiter les utilisateurs, monter les volumes en lecture seule quand possible, etc.).
Une bonne nouvelle pour la sécurité : les technologies conteneur intègrent des mécanismes puissants. Les capabilités Linux permettent de fragmenter les privilèges du root (un conteneur n’a que ceux dont il a besoin). À titre d’exemple, les processus dans un conteneur peuvent se voir refuser les appels système sensibles (grâce à AppArmor, seccomp, etc.), renforçant l’isolement. Mieux encore, des outils comme Podman tournent rootless par défaut, ce qui signifie que le daemon de conteneurs n’a pas les privilèges du super-utilisateur de l’hôte. Podman s’exécute comme un simple utilisateur Linux et n’utilise pas de daemon central, réduisant ainsi la surface d’attaque. Cette approche est plus sûre by-design que l’architecture classique de Docker (daemon rootful).
Au-delà du processus, il faut aussi penser réseau et pare-feu. Chaque conteneur possède son propre namespace réseau (interfaces virtuelles, règles iptables isolées), ce qui est une bonne nouvelle pour compartimenter le trafic. En revanche, il ne faut pas oublier le filtrage à l’échelle de l’hôte. Des outils comme CrowdSec ou Fail2ban doivent être déployés idéalement sur l’hôte (ou sur un reverse proxy) pour surveiller le trafic entrant vers tous les services conteneurisés. Un conteneur compromis peut toujours tenter de se propager sur le réseau local : il faut donc cloisonner les réseaux (par exemple VLAN ou bridges différents pour DMZ, LAN privé, VPN) et mettre à jour régulièrement le système hôte. En somme, "sécuriser les conteneurs" signifie souvent sécuriser l’hôte au même titre qu’une VM traditionnelle : bonnes configurations, least privilege, mises à jour automatiques, scan d’images (Trivy, Clair…), etc.
Réseau et orchestration
Du côté réseau, les conteneurs offrent les mêmes possibilités qu’une VM : on peut utiliser des ponts (bridges) Linux, du NAT, ou des réseaux overlay dans un cluster. Par défaut, Docker/Podman créent souvent un réseau pont (bridge) pour isoler les pods, et on peut mapper les ports nécessaires vers l’extérieur. J’utilise par exemple Nginx Proxy Manager (lui-même conteneurisé) pour exposer mes apps comme Nextcloud ou Gitea, avec des certificats Let’s Encrypt gérés automatiquement. Rien d’intrinsèquement plus complexe qu’avec des VM, mis à part la configuration des règles iptables au départ.
Côté orchestration, tout dépend de l’échelle. Pour quelques services sur un serveur unique, Docker Compose (ou Podman Compose) et Portainer suffisent amplement. Ils permettent de définir un stack multi-conteneurs avec un simple fichier YAML.
Pour les plus téméraires, il existe K3s ou K8s sur homelab, mais ce n’est pas nécessairement adapté si on a juste quelques applications à faire tourner. J’ai constaté que pour mes besoins (monitoring, Git, chat, Nextcloud…), un compose par service et une interface Portainer (qui reconnait aussi Podman) me simplifiat la vie. Si je devais monter à l’échelle, Kubernetes deviendrait pertinent, mais ce n’est pas l’urgence ici.
VM vs conteneurs : quelle combinaison ?
Dans mon homelab actuel, Proxmox VE sert de fondation. J’utilise des machines virtuelles (VM) pour isoler certains environnements :
- certaines VMs sont « bare services » (un seul service tournant directement sur la VM, comme un serveur dédié à Nextcloud) ;
- d’autres hébergent plusieurs conteneurs Docker pour des services complémentaires (par exemple, Portainer, Nginx Proxy Manager et CrowdSec regroupés dans la même VM).
Cette approche permet de combiner la souplesse des conteneurs (déploiement rapide, gestion simplifiée) avec la sécurité et l’isolation offertes par la virtualisation complète.
Le forum Proxmox résume bien ce choix : « Si on veut un service le plus sécurisé et indépendant possible, ou utiliser des OS non-Linux (Win/Mac), on utilise une VM. Si on veut un Linux proche d’une VM mais avec moins de surcharge (coût de sécurité), on utilise un LXC. Si on veut juste déployer des applis sans se soucier de les administrer, on peut lancer Docker dans une VM. » Pour ma part, Nextcloud, Grafana et VaultWarden tournent en containers (dans une VM Debian, pour la commodité de la migration), tandis que mes bases de données critiques (PostgreSQL, MariaDB) restent sur une VM avec stockage dédié. Keycloak, qui gère l’authentification, est aussi en container mais très isolé derrière le proxy. Cette configuration "mixte" me donne l’agilité des containers tout en gardant une couche de sécurité VM là où elle compte.
Possibilitée
Au final, il n’y a pas de réponse universelle "tout container, tout de suite". Le bon équilibre dépend des objectifs : performance et densité de service, portabilité et DevOps, versus sécurité et stabilité. Dans mon homelab, je penche aujourd’hui pour une approche hybride : les conteneurs (Docker/Podman) pour les services applicatifs facilement remplaçables et fréquemment mis à jour, et quelques VM pour les services système critiques ou les containers nécessitant une protection accrue. Quoi qu’il en soit, l’habitude de containeriser m’a grandement fait progresser sur la reproductibilité et la gestion de versions.
À vous de peser les avantages (rapidité de déploiement, cohérence grâce aux images) face aux contraintes (moindre isolation, configuration réseau/stockage).
Conseil pratique : commencez par conteneuriser ce qui peut l’être (sites web, microservices) pour tester l’approche ; gardez VM ou bare-metal pour les briques lourdes (bases de données, pare-feux d’entreprise, serveurs de fichiers critiques). En tous cas, gardez toujours en tête la sécurité en renforçant les conteneurs (rootless, listes blanches d’appels système, mises à jour régulières) et en protégeant l’hôte (firewall, sauvegardes, monitoring).