Sécurité Docker et Kubernetes : conteneurs sécurisés et cluster défendable

Docker encapsule votre application et ses dépendances dans une image immuable ; Kubernetes orchestre ces conteneurs à l’échelle du cluster. Ensemble, ils simplifient le déploiement — mais une mauvaise configuration peut transformer un simple conteneur en pivot pour attaquer le reste de l’infrastructure. Ce guide pose les bases de la sécurité Docker, de la sécurité Kubernetes et d’un cluster sécurisé, pour développeurs et DevOps débutants à intermédiaires, avec des exemples concrets et des scénarios d’attaque réalistes.

Il complète les autres volets d’OmbreLoup Sec : DevSecOps Basics, sécurité API, CI/CD sécurisé et outillage.

[Emplacement pub - début article] 336×250

Pourquoi sécuriser Docker et Kubernetes est critique

Un conteneur n’est pas une machine virtuelle complète : il partage le noyau de l’hôte. Si un processus root dans le conteneur exploite une faille du runtime ou du noyau, les conséquences peuvent dépasser le simple pod. Côté Kubernetes, le plan de données (kubelet, CNI, stockage) et le plan de contrôle concentrent les secrets de l’organisation : tokens de service, certificats, accès au cloud.

Sans isolation ni contrôle d’accès, une compromission — image trojanisée, credential volé, NetworkPolicy absente — permet souvent une élévation de privilèges ou un mouvement latéral entre namespaces. Les rapports d’incidents montrent régulièrement des clusters exposés sur Internet (API server, dashboards) ou des workloads over-privileged qui facilitent la prise d’empreinte du cluster.

En résumé : sécuriser Docker réduit la surface dans chaque image ; sécuriser Kubernetes structure la défense en profondeur (identité, réseau, politiques de pods). Les deux s’alignent avec une approche DevSecOps : la même image doit être scannée en CI (pipeline sécurisé) et durcie au runtime.

Comprendre Docker : image, runtime et surface d’attaque

Une image est empilée de couches en lecture seule ; un conteneur est une instance exécutable de cette image. La sécurité Docker commence par ce que vous mettez dans l’image et comment le processus tourne.

Pourquoi éviter l’utilisateur root dans le conteneur

Par défaut, beaucoup d’images historiques lancent le processus en root (UID 0). En cas de vulnérabilité applicative ou de mauvaise isolation du runtime, un attaquant part avec les privilèges maximum à l’intérieur du conteneur — ce qui facilite l’élévation vers l’hôte selon le contexte (capabilities, montages).

Créer un utilisateur dédié et basculer avec USER limite ce que le processus peut faire même si le code est compromis :

FROM node:20-alpine
RUN addgroup -g 1001 app && adduser -u 1001 -G app -D app
WORKDIR /app
COPY --chown=app:app . .
USER app
CMD ["node", "index.js"]

Sur Kubernetes, combinez cela avec Pod Security Standards (profil restricted) pour refuser les pods qui exigent root ou des capabilities dangereuses.

Images minimales et surface d’attaque

Chaque paquet inutile dans l’image est une CVE potentielle. Les images Alpine, distroless ou les images « slim » réduisent les binaires présents : moins de shell, moins d’outils pour un attaquant, moins de mises à jour à suivre. Ce n’est pas de l’esthétique : c’est une réduction mesurable de la surface d’attaque pour des conteneurs sécurisés.

Scanner les images (Trivy) et intégrer le secret hors de l’image

Avant de pousser vers un registry, analysez l’image avec Trivy (ou équivalent) :

trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest

Les secrets (clés API, PEM) ne doivent jamais être copiés dans l’image : utilisez des variables d’environnement injectées au runtime, Kubernetes Secrets (idéalement chiffrés au repos avec KMS ou external-secrets / Vault), ou des références au secret manager de votre cloud. Une image publiée avec un .env embarqué est une fuite en attente.

Kubernetes : un cluster sécurisé repose sur l’identité, le réseau et les politiques

RBAC : qui peut faire quoi dans le cluster

Le RBAC (Role-Based Access Control) lie des Roles (ou ClusterRoles) à des sujets (User, ServiceAccount) via des RoleBindings. Sans RBAC strict, un compte de déploiement peut par exemple lire tous les secrets du cluster — scénario classique après vol de token.

Exemple minimal : lecture seule sur un namespace pour un outil d’observabilité :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: reader
rules:
  - apiGroups: [""]
    resources: ["pods", "services"]
    verbs: ["get", "list", "watch"]

Principe : moindre privilège — accorder uniquement les verbs et resources nécessaires ; les ServiceAccounts par défaut ne doivent pas avoir des droits étendus « pour faire vite ».

Network Policies : isolation des workloads (cas concret)

Sans NetworkPolicy, tout pod peut généralement joindre tout autre pod sur le réseau overlay : un conteneur compromis (web vulnérable) peut scanner le réseau et atteindre une base de données ou l’API Kubernetes.

Cas concret : un namespace frontend ne doit parler qu’au service api sur le port 8080 ; la base postgres n’accepte que le trafic depuis les pods avec le label role=api.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
spec:
  podSelector: {}
  policyTypes:
    - Ingress

Une politique « deny all » par défaut, puis des règles explicites par application, segmentent les workloads et limitent la propagation après compromission.

Pod Security Standards et secrets

Les Pod Security Standards (profils privileged, baseline, restricted) s’appliquent au niveau namespace : par exemple restricted impose utilisateur non-root, pas de montage sensible arbitraire, etc.

Pour les Secrets Kubernetes : préférez le chiffrement au repos (etcd chiffré, KMS), rotation, et évitez de monter des secrets en clair dans des volumes partagés sans besoin. Les applications exposées en HTTP doivent aussi suivre les bonnes pratiques sécurité API — le conteneur sain ne remplace pas TLS ni auth applicative.

[Emplacement pub - milieu article] 728×90

Cas d’attaque réels (simplifiés)

Conteneur compromis via image ou vulnérabilité

Une image tirée d’un registry public est trojanisée ou une CVE critique dans une lib système permet l’exécution de code. Sans réseau segmenté, le malware tente la sortie vers Internet ou le mouvement latéral. Réponse : images signées, scans, NetworkPolicy, runtime security (Falco, etc. — voir outils).

Élévation de privilèges

Un pod monté avec privileged: true ou avec toutes les capabilities peut faciliter l’échappement vers le nœud. Les politiques PSS et des SecurityContext stricts (runAsNonRoot, readOnlyRootFilesystem quand possible) réduisent cette surface.

Mauvaise configuration Kubernetes

API Server exposé, kubeconfig commité, dashboard non protégé : autant de portes ouvertes documentées dans la littérature offensive. Durcissement du plan de contrôle, authentification forte pour l’accès humain et audit des kubectl sont indispensables pour un cluster sécurisé.

Erreurs fréquentes

Bonnes pratiques avancées : isolation et défense en profondeur

Ces pratiques renforcent l’isolation des workloads : chaque application vit dans une « bulle » définie par identité, réseau et politique de pod — exactement ce qu’attend un modèle DevSecOps mature, décrit dans nos fondamentaux.

Conclusion

La sécurité Docker et la sécurité Kubernetes se construisent couche par couche : images minimales et scannées, processus non-root, secrets hors des images, RBAC minimal, Network Policies explicites, Pod Security Standards et cluster à jour. Ce n’est pas une liste de cases à cocher pour un audit : c’est une façon de livrer des conteneurs sécurisés sans figer la vélocité des équipes.

Pour aller plus loin sur OmbreLoup Sec : DevSecOps Basics, Sécurité API, CI/CD Security et Outils & Ressources (Trivy, kube-bench, Falco, politiques, etc.).