Jour 1 : Docker et les Conteneurs pour la Certification CKA
Docker expliqué pour débuter votre préparation à la certification CKA.

Docker est la base sur laquelle Kubernetes s’appuie pour orchestrer des applications conteneurisées à grande échelle. Maîtriser Docker constitue donc une première étape indispensable.


Jour 1

Bienvenue dans cette série dédiée à la préparation à la certification Certified Kubernetes Administrator (CKA). Cette formation pas à pas est conçue pour vous guider dans l’apprentissage et la maîtrise des concepts fondamentaux et des compétences pratiques essentiels pour obtenir cette certification reconnue mondialement. Tout au long de cette série, vous explorerez des sujets essentiels tels que :

  • La conteneurisation avec Docker et son rĂ´le dans l’écosystème Kubernetes.
  • Les bases de Kubernetes, incluant la gestion des pods, services et dĂ©ploiements.
  • L’administration des clusters Kubernetes, avec un accent sur la haute disponibilitĂ© et la sĂ©curitĂ©.
  • La rĂ©solution des dĂ©fis courants rencontrĂ©s par les administrateurs Kubernetes en environnements de production.

Chaque tutoriel est structuré pour offrir une progression claire, mêlant théorie et pratique, afin de renforcer vos compétences techniques. Que vous soyez débutant ou déjà expérimenté, cette série vous fournira les outils nécessaires pour exceller à votre examen CKA et dans vos projets professionnels.

Prenez le temps d’expérimenter chaque étape, et n’hésitez pas à revenir sur les concepts clés si nécessaire. Bonne préparation et bonne chance dans votre parcours vers la certification CKA !



1. Introduction Ă  Docker

1.1. Qu’est-ce que Docker ?

Docker est une plateforme open-source puissante conçue pour simplifier le développement, le déploiement et l’exécution d’applications via la conteneurisation. Les conteneurs offrent des environnements légers, portables et isolés qui encapsulent une application ainsi que ses dépendances. Cela garantit un comportement cohérent à travers divers environnements informatiques. Docker est devenu indispensable pour les systèmes logiciels modernes, offrant une rapidité, une efficacité et une évolutivité incomparables.

La simplicité et la puissance de Docker en ont fait un outil révolutionnaire pour les équipes de développement. Il permet des workflows cohérents, que vous programmiez sur votre ordinateur portable, testiez dans un pipeline CI/CD, ou déployiez sur des clusters de production.

1.2. Comprendre les Conteneurs vs les Machines Virtuelles

Architecture d'une VM vs Conteneurs (source : <a href='https://www.open-telekom-cloud.com/en/blog/cloud-computing/container-vs-vm'>Open Telekom</a>)
Architecture d'une VM vs Conteneurs (source : Open Telekom)

Les conteneurs et les machines virtuelles (VMs) facilitent tous deux des environnements d’application isolés, mais leurs mécanismes sous-jacents diffèrent fondamentalement :

  • Machines Virtuelles (VMs) :
    • Fonctionnent via une couche d’hyperviseur, comme VMware ou VirtualBox, exĂ©cutant un système d’exploitation (OS) invitĂ© complet.
    • Consomment beaucoup de ressources, car chaque VM inclut son propre noyau OS.
    • Temps de dĂ©marrage relativement longs en raison de l’initialisation complète du système d’exploitation.
  • Conteneurs :
    • Partagent le noyau OS de l’hĂ´te, Ă©liminant la surcharge d’un système d’exploitation invitĂ© supplĂ©mentaire.
    • LĂ©gers, contenant uniquement l’application et ses dĂ©pendances.
    • Temps de dĂ©marrage rapides et consommation minimale de ressources, les rendant plus efficaces.

1.3. Conteneurs vs Machines Virtuelles : une analogie

Pour clarifier la différence, considérons l’analogie des bâtiments résidentiels :

  • Machines Virtuelles : Elles sont analogues Ă  des maisons individuelles. Chaque maison possède ses propres fondations, murs, plomberie et Ă©lectricitĂ©, Ă  l’image d’un système d’exploitation complet. Bien qu’isolĂ©es, elles nĂ©cessitent des ressources significatives pour ĂŞtre construites et maintenues.

  • Conteneurs : Ceux-ci ressemblent Ă  des appartements dans un immeuble partagĂ©. Les appartements partagent une infrastructure commune (fondations, murs, utilitĂ©s), comme le noyau OS de l’hĂ´te. Chaque appartement est autonome mais plus lĂ©ger et plus rapide Ă  construire qu’une maison individuelle.

1.4. Défis des Applications Non-Conteneurisées

Avant l’avènement de la conteneurisation, les applications faisaient face à plusieurs défis inhérents :

  1. Conflits de Dépendances : Les différentes applications nécessitaient souvent des versions incompatibles des mêmes bibliothèques ou environnements d’exécution, provoquant des conflits.

  2. Incohérences Environnementales : Les applications fonctionnaient fréquemment sur la machine locale d’un développeur mais échouaient en production en raison de différences environnementales.

  3. Inefficacité des Ressources : Exécuter plusieurs applications sur la même machine nécessitait des machines virtuelles gourmandes en ressources ou des configurations complexes.

  4. Limitations de Scalabilité : Faire évoluer ou mettre à jour des applications était laborieux, sujet aux erreurs et chronophage.

1.5. Comment Docker RĂ©sout Ces DĂ©fis

Docker répond efficacement à ces défis systémiques :

  1. Isolation : Les conteneurs encapsulent toutes les dépendances nécessaires, éliminant ainsi les conflits entre les applications.

  2. Portabilité : Les conteneurs garantissent un comportement cohérent des applications à travers différents environnements—du développement aux tests en passant par la production.

  3. Efficacité : Le partage du noyau OS de l’hôte réduit la consommation de ressources et accélère les temps de démarrage.

  4. Scalabilité : Docker simplifie le scaling horizontal en permettant le déploiement rapide de plusieurs conteneurs issus de la même image.

Passons maintenant de la théorie à la pratique pour découvrir comment utiliser Docker efficacement.

1.6. Un Workflow Docker Simple

Pour comprendre l’utilité de Docker, explorons son workflow de base :

  1. Écrire un Dockerfile : Créez un Dockerfile pour définir le modèle de votre conteneur, spécifiant l’image de base, le code de l’application et les dépendances.

  2. Construire une Image : Exécutez docker build pour compiler une image à partir du Dockerfile.

  3. Exécuter un Conteneur : Utilisez docker run pour instancier et exécuter un conteneur à partir de l’image, créant un environnement d’exécution isolé.

  4. Pousser vers un Registre : Enregistrez et partagez l’image en la poussant vers un registre de conteneurs (par ex., Docker Hub) avec docker push.

  5. Tirer et Déployer : Téléchargez et déployez l’image sur un autre système avec docker pull, garantissant un comportement d’application cohérent.

1.7. L’Architecture Docker

L'Architecture Docker (source : <a href='https://docs.docker.com/get-started/docker-overview/#docker-architecture'>Documentation officielle Docker</a>)
L'Architecture Docker (source : Documentation officielle Docker)

L’architecture Docker comprend plusieurs composants essentiels :

  1. Client Docker : L’interface utilisateur pour interagir avec Docker. Les commandes comme docker build et docker run sont transmises au Daemon Docker.

  2. Daemon Docker (dockerd) : Le service central qui gère les images, les conteneurs et leur cycle de vie. Il traite les requêtes du client et coordonne les opérations.

  3. Images : Modèles immuables pour créer des conteneurs. Elles encapsulent l’environnement et les dépendances de l’application.

  4. Conteneurs : Instances légères des images qui fournissent un environnement d’exécution pour l’exécution des applications.

  5. Registre Docker : Un dépôt centralisé pour stocker et distribuer les images Docker (par ex., Docker Hub ou des registres privés).

  6. Runtime de Conteneurs : Le moteur sous-jacent responsable de l’exécution des conteneurs. Le runtime de Docker, tel que containerd, garantit une exécution efficace des conteneurs.

Ce guide offre une compréhension fondamentale des capacités de Docker et de son rôle transformateur dans le développement logiciel moderne. À mesure que vous approfondissez vos connaissances, expérimentez les fonctionnalités de Docker pour maîtriser la conteneurisation et simplifier le déploiement des applications.


2. Installation de Docker

Avant de pouvoir conteneuriser un projet, assurez-vous que Docker est installé sur votre système. Voici les deux options principales :

2.1. Utilisation de Docker Desktop (solution complète mais lourde)

  • Avantages : Simple Ă  installer, avec une interface graphique et des outils intĂ©grĂ©s.
  • InconvĂ©nients : Alourdit votre système en installant des composants souvent inutiles pour la prĂ©paration au CKA. La licence peut Ă©galement poser problème en entreprise.
  • Étapes :
    1. Téléchargez Docker Desktop depuis docker.com.
    2. Installez et lancez Docker Desktop.

2.2. Installation des composants Docker individuellement (recommandée)

  • Avantages : Installation lĂ©gère, adaptĂ©e Ă  une prĂ©paration au CKA.
  • InconvĂ©nients : NĂ©cessite quelques Ă©tapes supplĂ©mentaires sur macOS et Windows.

2.2.1. Pour Windows avec WSL2

wsl --install
Powershell
  • Étape 2 - Ouvrez la distribution Ubuntu Linux qui s’est installĂ©e et suivez les Ă©tapes d’installation pour Linux ci-dessous.

2.2.2. Pour Linux

  • Étape 1 - Mettez Ă  jour vos dĂ©pĂ´ts :
sudo apt update
Bash
  • Étape 2 - Installez Docker :
sudo apt install docker.io
Bash
  • Étape 3 - Activez et dĂ©marrez Docker :
sudo systemctl enable docker
sudo systemctl start docker
Bash
  • Étape 4 - Ajoutez votre utilisateur au groupe Docker (pour Ă©viter d’utiliser sudo) :
sudo usermod -aG docker $USER
Bash

Redémarrez votre terminal pour appliquer les modifications.

2.2.3. Pour macOS avec Docker CLI et Colima

  • Étape 1 - Installez le client Docker avec Homebrew :
brew install docker
Bash
  • Étape 2 - Installez Colima avec Homebrew :
brew install colima
Bash

Pourquoi Colima ?

  • macOS nĂ©cessite Colima pour exĂ©cuter Docker, car son noyau Darwin (BSD-based) ne prend pas en charge nativement les fonctionnalitĂ©s de conteneurisation Linux comme les namespaces et les cgroups.
  • Colima est un outil lĂ©ger basĂ© sur Lima qui crĂ©e une machine virtuelle Linux optimisĂ©e pour exĂ©cuter le daemon Docker, offrant ainsi un environnement compatible.
  • Étape 3 - DĂ©marrez Colima pour initier le daemon Docker :
colima start -f
Bash

2.3. Test de l’installation

  • Lancer la commande docker suivante pour testez votre installation :
docker run hello-world
Bash

Vous devriez voir un message indiquant que tout fonctionne comme ci-dessous.

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
Output

En suivant ces étapes, vous aurez un environnement Docker configuré et fonctionnel, que ce soit pour des tests locaux, le développement ou la préparation à l’orchestration avec Kubernetes.

Alternatives Ă  Docker

Bien que Docker reste l’outil de référence pour la conteneurisation, de nombreuses alternatives sont désormais disponibles. Parmi les principales solutions pouvant remplacer le daemon Docker ou le client Docker, on peut citer :

  • Podman : Une alternative sans daemon avec une interface similaire Ă  Docker.
  • Containerd : Un runtime conteneur lĂ©ger utilisĂ© par Docker lui-mĂŞme, pouvant ĂŞtre utilisĂ© directement.
  • CRI-O : Un runtime conteneur optimisĂ© pour Kubernetes, respectant l’interface CRI.

Cependant, dans le cadre de la préparation à la certification CKA, il est recommandé d’utiliser Docker pour garantir une familiarité avec les bases et les outils souvent mentionnés dans la documentation.


3. Utilisation de Dockker : Tutoriel Étape par Étape

Ce tutoriel vous guidera dans le processus de conteneurisation d’un projet avec Docker. À la fin de ce guide, vous saurez comment créer un Dockerfile, construire et pousser une image Docker, et travailler avec des conteneurs.

3.1. Le Dockerfile (Approche de Base)

Commençons par une approche simple. Cela nous permettra d’en comprendre les limitations et de les comparer avec une approche plus optimisée.

  • Étape 1 - CrĂ©ez un rĂ©pertoire pour votre projet :
mkdir docker-c-app
cd docker-c-app
Bash
  • Étape 2 - CrĂ©ez un fichier main.c contenant :
#include <stdio.h>

int main() {
    printf("Bienvenue dans votre application Docker !\n");
    return 0;
}
C
  • Étape 3 - CrĂ©ez un premier fichier Dockerfile :
# Utiliser une image contenant GCC pour compiler et exécuter l'application
FROM gcc:latest

# Définir le répertoire de travail
WORKDIR /app

# Copier le fichier source
COPY main.c .

# Compiler l'application
RUN gcc -o app main.c

# Définir la commande par défaut
CMD ["./app"]
Dockerfile

Syntaxe des Dockerfiles

Pour une compréhension approfondie de la syntaxe et des concepts des Dockerfiles, vous pouvez consulter la documentation officielle : Dockerfile Reference.

  • Étape 4 - Construisez l’image Docker :
docker build -t c-app-basic:1.0.0 .
Bash

Explication de la commande :

  • docker build : Cette commande crĂ©e une image Docker Ă  partir des instructions dĂ©finies dans le fichier Dockerfile prĂ©sent dans le rĂ©pertoire courant.
  • -t c-app-basic : L’option -t permet d’attribuer un nom (ici c-app-basic) et un tag (1.0.0) Ă  l’image. Si aucun tag explicite n’est prĂ©cisĂ©, Docker utilise latest par dĂ©faut.
  • . : Ce point indique que le contexte de construction est le rĂ©pertoire courant, oĂą Docker recherche le Dockerfile et les fichiers nĂ©cessaires pour construire l’image.

Une fois cette commande exécutée, Docker lit les instructions du Dockerfile, crée l’image et l’enregistre localement dans votre système.

  • Étape 5 - VĂ©rifiez que l’image a Ă©tĂ© crĂ©Ă©e :
docker images
Bash

Cette commande affiche la liste des images Docker présentes sur votre système local :

% docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
c-app-basic   1.0.0     70543dee1b46   4 minutes ago   1.39GB
gcc           latest    d18c3b309576   5 months ago    1.39GB
hello-world   latest    ee301c921b8a   20 months ago   9.14kB
Output

Recherchez le nom c-app-basic dans la liste pour confirmer que l’image a bien été créée avec succès.

  • Étape 6 - ExĂ©cutez le conteneur :
docker run --rm c-app-basic:1.0.0
Bash

Explication de la commande :

  • docker run : Cette commande dĂ©marre un nouveau conteneur Ă  partir de l’image spĂ©cifiĂ©e, ici c-app-basic:1.0.0.
  • --rm : Cette option indique que le conteneur sera automatiquement supprimĂ© après son exĂ©cution. Cela permet de garder votre environnement propre et d’éviter d’accumuler des conteneurs inutilisĂ©s.
  • c-app-basic:1.0.0 : Nom de l’image et tag Ă  partir desquels le conteneur a Ă©tĂ© crĂ©Ă©.

Lorsque vous exécutez cette commande, Docker crée puis démarre un conteneur basé sur l’image c-app-basic et du tag 1.0.0. Une fois le programme dans le conteneur terminé, vous verrez le message suivant dans le terminal :

Bienvenue dans votre application Docker !
Output

Après l’exécution, le conteneur sera supprimé grâce à l’option --rm.

Référence des commandes Docker CLI

Pour découvrir et maîtriser les commandes essentielles de Docker CLI, consultez la fiche pratique officielle : Docker CLI Cheat Sheet.

3.2. Problème avec l’Approche de Base

L’approche de base, bien qu’elle soit fonctionnelle, présente plusieurs inconvénients majeurs :

  • Taille excessive de l’image : L’image finale inclut tous les outils nĂ©cessaires Ă  la compilation, comme gcc, ainsi que d’autres bibliothèques et dĂ©pendances non nĂ©cessaires pour exĂ©cuter l’application. Cela augmente considĂ©rablement la taille de l’image, la rendant plus lourde Ă  transfĂ©rer et Ă  dĂ©ployer.

  • Surface d’attaque accrue : Les outils de compilation, bien qu’utiles pendant le processus de build, n’ont aucune utilitĂ© dans l’image finale. Leur prĂ©sence Ă©largit la surface d’attaque potentielle, exposant l’image Ă  des vulnĂ©rabilitĂ©s inutiles dans un environnement de production.

  • Non-optimisation pour la production : Une bonne pratique en production est de ne conserver que les fichiers nĂ©cessaires Ă  l’exĂ©cution de l’application. Dans cette approche, les fichiers temporaires de build et les outils de compilation augmentent la complexitĂ© inutilement.

Pour vérifier la taille de l’image générée avec cette approche de base, utilisez la commande suivante :

docker images | grep c-app-basic
Bash

La grande taille de cette image (1.39Go) met en évidence l’importance d’optimiser les processus de construction avec une approche comme la construction multi-stage, qui sera explorée dans la section suivante.

3.3. Construction Multi-Stage avec Docker

La construction multi-stage est une technique qui permet de créer des images Docker optimisées en séparant le processus de build de l’application de celui de l’image. Chaque étape utilise une image spécifique et contribue à construire progressivement l’application, mais seules les parties nécessaires sont incluses dans l’image finale.

3.3.1. Avantages du multi-stage

  1. Réduction de la taille de l’image : Les outils de compilation et autres fichiers temporaires restent dans les étapes intermédiaires et ne sont pas inclus dans l’image finale.
  2. Sécurité améliorée : En excluant les outils inutiles comme gcc ou les bibliothèques de build, on réduit la surface d’attaque potentielle.
  3. Optimisation pour la production : L’image finale est minimale, ne contenant que ce qui est nécessaire à l’exécution de l’application.

3.3.2. Fonctionnement du multi-stage

Le fichier Dockerfile est structuré en plusieurs étapes. Une étape peut s’appuyer sur une autre en utilisant la directive COPY --from=<nom_étape>. Par exemple :

  1. Une première étape appelée étape de construction inclut tous les outils nécessaires pour compiler ou assembler le projet.
  2. Une étape suivante appelée étape finale récupère uniquement les fichiers nécessaires à l’exécution de l’application et utilise une image de base légère, comme alpine ou chainguard, pour réduire la taille de l’image.

3.3.3. Mise en Pratique

Pour résoudre les problèmes mentionnés dans l’approche de base, utilisons une construction multi-stage pour notre application :

  • Étape 1 - Modifiez le Dockerfile pour inclure plusieurs Ă©tapes :
# Étape de construction
FROM gcc:latest as builder

# Définir le répertoire de travail
WORKDIR /app

# Copier le fichier source
COPY main.c .

# Compiler l'application
RUN gcc -o app main.c

# Étape finale
FROM chainguard/glibc-dynamic

# Définir le répertoire de travail
WORKDIR /app

# Copier l'exécutable depuis l'étape de construction
COPY --from=builder /app/app .

# Définir la commande par défaut
CMD ["./app"]
Dockerfile
  • Étape 2 - Construisez l’image en multi-stage :
docker build -t c-app-optimized:1.0.0 .
Bash
  • Étape 3 - ExĂ©cutez le conteneur :
docker run --rm c-app-optimized:1.0.0
Bash

Vous verrez le même message dans le terminal : Bienvenue dans votre application Docker !

  • Étape 4 - Comparer la diffĂ©rence de taille :
docker images | grep c-app
Bash

Dans mon cas et à date, j’obtiens :

% docker images | grep c-app
c-app-optimized            1.0.0     cd510de25230   17 minutes ago      9.56MB
c-app-basic                1.0.0     70543dee1b46   About an hour ago   1.39GB
Output
  • Vous remarquerez que l’image optimisĂ©e est beaucoup plus petite (99% plus petite pour cette application certes très simple) grâce Ă  l’utilisation d’une image lĂ©gère (chainguard/glibc-dynamic) et Ă  l’élimination des outils de compilation inutiles.

3.4. Résumé des Avantages de la Construction Multi-Stage

  • RĂ©duction de la taille de l’image : L’image optimisĂ©e est beaucoup plus petite et rapide Ă  dĂ©ployer.
  • SĂ©curitĂ© amĂ©liorĂ©e : Les outils de compilation et les fichiers inutiles sont exclus de l’image finale.
  • Pratiques modernes : La construction multi-stage est une meilleure approche pour les environnements de production.

En comparant les deux approches, vous avez pu voir comment une construction multi-stage simplifie la gestion des conteneurs tout en réduisant les risques et les ressources.


4. Conclusion

Les conteneurs autonomes, bien qu’utiles pour des applications simples, posent des défis en termes de scalabilité, de gestion des ressources et d’orchestration lorsqu’ils sont déployés dans des systèmes plus complexes. Gérer le réseau, l’équilibrage de charge, et garantir une haute disponibilité manuellement devient de plus en plus difficile avec l’augmentation de la complexité de l’application.

Kubernetes résout ces défis en automatisant le déploiement, le scaling et la gestion des applications conteneurisées. Il offre des capacités d’auto-réparation, d’équilibrage de charge, d’optimisation des ressources et de configuration déclarative, le rendant idéal pour gérer des applications en environnement de production.

4.1. Quand Utiliser Kubernetes

  • Applications avec une architecture de microservices nĂ©cessitant une orchestration.
  • Environnements nĂ©cessitant une haute scalabilitĂ© et une tolĂ©rance aux pannes.
  • Pipelines CI/CD pour des tests et dĂ©ploiements cohĂ©rents.
  • DĂ©ploiements multi-cloud ou hybrides pour rĂ©partir les charges de travail.
  • Applications avec des besoins dynamiques en trafic et en ressources.

4.2. Quand Ne Pas Utiliser Kubernetes

  • Applications petites et Ă  conteneur unique.
  • Prototypes ou projets d’apprentissage oĂą la simplicitĂ© est essentielle.
  • Systèmes avec des budgets ou des ressources limitĂ©s.
  • Charges de travail statiques qui ne nĂ©cessitent pas de mises Ă  jour ou de scalabilitĂ© frĂ©quentes.
  • Systèmes en temps rĂ©el nĂ©cessitant une ultra-faible latence, oĂą l’abstraction de Kubernetes pourrait ajouter un dĂ©lai.

En intégrant des outils comme Docker avec Kubernetes, vous pouvez créer des environnements évolutifs et efficaces adaptés aux besoins de votre application. Cependant, évaluez toujours les compromis pour vous assurer que Kubernetes correspond à l’échelle et à la complexité de votre projet.

Jean-Jerome Levy

Ecrit par

Jean-JĂ©rĂ´me LĂ©vy

Consultant DevOps

Professionnel chevronné dans le domaine de l’informatique, cumulant plus de 20 années d’expérience au sein de DSI de grandes entreprises, mon expertise diversifiée m’a permis de jouer un rôle clé dans de nombreux projets, caractérisés par la mise en place de pratiques DevOps innovantes.