Les conteneurs ne sont pas une technologie autonome — ils sont une combinaison de fonctionnalités du noyau Linux existant depuis des années. Comprendre namespaces et cgroups explique pourquoi les conteneurs sont rapides, légers, et quelles sont leurs vraies limites d’isolation.
Les namespaces : isolation des ressources
Un namespace limite ce qu’un processus peut voir. Linux dispose de 7 types de namespaces, chacun isolant une catégorie de ressources différente.
# Voir les namespaces d'un processus
ls -la /proc/1/ns/
# lrwxrwxrwx cgroup → cgroup:[4026531835]
# lrwxrwxrwx ipc → ipc:[4026531839]
# lrwxrwxrwx mnt → mnt:[4026531840]
# lrwxrwxrwx net → net:[4026531992]
# lrwxrwxrwx pid → pid:[4026531836]
# lrwxrwxrwx user → user:[4026531837]
# lrwxrwxrwx uts → uts:[4026531838]
PID namespace — les processus voient un arbre de PID indépendant. Le premier processus dans le namespace a le PID 1.
# Créer un nouveau PID namespace
unshare --pid --fork --mount-proc /bin/bash
# Dans le nouveau namespace
ps aux
# UID PID PPID CMD
# root 1 0 /bin/bash ← PID 1 dans ce namespace
# root 8 1 ps aux
Network namespace — interface réseau, table de routage et règles iptables isolées.
# Créer un network namespace
ip netns add mycontainer
# Créer une paire d'interfaces veth (comme un câble réseau virtuel)
ip link add veth0 type veth peer name veth1
ip link set veth1 netns mycontainer
# Configurer les adresses
ip addr add 192.168.100.1/24 dev veth0
ip link set veth0 up
ip netns exec mycontainer ip addr add 192.168.100.2/24 dev veth1
ip netns exec mycontainer ip link set veth1 up
# Test
ip netns exec mycontainer ping 192.168.100.1
Mount namespace — chaque conteneur a son propre système de fichiers monté.
UTS namespace — hostname et domaine NIS isolés (chaque conteneur peut avoir son propre hostname).
User namespace — UID/GID mappés. Permet à root dans le conteneur d’être un utilisateur non-privilégié sur l’hôte.
cgroups v2 : limiter les ressources
Les cgroups (control groups) limitent ce qu’un processus peut utiliser en termes de ressources CPU, mémoire, I/O.
# Créer un cgroup
mkdir /sys/fs/cgroup/myapp
# Limiter la mémoire à 512MB
echo "536870912" > /sys/fs/cgroup/myapp/memory.max
# Limiter le CPU à 50% (une période de 100ms, quota de 50ms)
echo "50000 100000" > /sys/fs/cgroup/myapp/cpu.max
# Assigner un processus au cgroup
echo $PID > /sys/fs/cgroup/myapp/cgroup.procs
# Vérifier la consommation
cat /sys/fs/cgroup/myapp/memory.current
cat /sys/fs/cgroup/myapp/cpu.stat
Comment Docker utilise ces primitives
# Docker crée automatiquement des namespaces et cgroups
docker run -d --name mycontainer --memory=512m --cpus=0.5 nginx
# Inspecter les namespaces créés par Docker
docker inspect mycontainer | grep Pid
# "Pid": 12345
ls -la /proc/12345/ns/
# Vous verrez des namespaces différents de ceux du PID 1 (init)
# Inspecter les cgroups
cat /sys/fs/cgroup/system.slice/docker-<id>.scope/memory.max
Les limites de l’isolation
Les conteneurs partagent le noyau du host. Contrairement aux VMs, une vulnérabilité du noyau peut impacter tous les conteneurs. C’est pourquoi :
- Les images
rootdans les conteneurs posent un risque si le user namespace n’est pas activé - Les capabilities Linux doivent être réduites au minimum
- Seccomp profiles filtrent les appels système dangereux
# Bonne pratique : créer un utilisateur non-root
FROM python:3.12-slim
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
USER appuser
Notre formation Linux couvre les namespaces, cgroups et la sécurité des conteneurs en profondeur.