🐳 Conteneurs et environnements applicatifs

Idée générale

L’objectif est de pouvoir crĂ©er un livrable unique qui permette de lancer notre application, prĂ©alablement configurĂ©e, afin de garantir son bon fonctionnement, quelle que soit la machine utilisĂ©e. C’est ce qu’on appelle la portabilitĂ© applicative.

Jusqu’Ă  prĂ©sent, pour exĂ©cuter une application Python sur une autre machine, plusieurs Ă©tapes sont nĂ©cessaires :

  1. Récupérer tous les fichiers .py du projet
  2. Ajouter les fichiers de configuration
  3. Disposer d’un environnement oĂč Python est installĂ©, dans une version compatible
  4. Installer toutes les dépendances du projet
  5. Lancer une ligne de commande pour dĂ©marrer l’application

C’est assez long, et il y a des risques d’erreurs.

Docker permet de crĂ©er un environnement prĂ©configurĂ© contenant le code de l’application, toutes les dĂ©pendances dĂ©jĂ  installĂ©es et une version de Python prĂ©cisĂ©ment dĂ©finie

Avec Docker, l’utilisateur n’a plus qu’à :

  1. Avoir Docker installé sur sa machine
  2. TĂ©lĂ©charger l’image Docker du projet
  3. Lancer cette image

Une image Docker, c’est quoi ?
Une image Docker, c’est un Ă©norme zip qui contient qui contient tout le nĂ©cessaire pour exĂ©cuter une application dans un environnement contrĂŽlĂ©. C’est une forme d’Infrastructure as Code, garantissant que si l’application fonctionne sur une machine, elle fonctionnera sur une autre (tant que Docker est disponible).

Ressources : Les fichiers présentés sur cette slide sont disponibles sur le dépÎt GitHub :
🔗 Cours 6 - Exemples

Conteneurs : Concepts clés

L’introduction de l’isolation des processus, mise en place en 2006, a permis de mieux gĂ©rer les interactions entre les diffĂ©rentes tĂąches d’un systĂšme. Cette avancĂ©e a transformĂ© notre approche de la livraison des logiciels. DĂ©sormais, nous pouvons proposer des modules qui fonctionnent de maniĂšre isolĂ©e du reste du systĂšme qui les hĂ©berge, tout en exĂ©cutant des traitements dans des environnements contrĂŽlĂ©s.

conteneur-runtime

Le terme container runtime dĂ©signe le logiciel responsable de la gestion des conteneurs, permettant d’exĂ©cuter des applications de maniĂšre isolĂ©e sur un mĂȘme systĂšme d’exploitation.

  1. Kernel :
    Les conteneurs partagent le mĂȘme systĂšme d’exploitation (OS) mais hĂ©bergent des processus indĂ©pendants. Chaque conteneur fonctionne comme une entitĂ© autonome, mais ils utilisent tous le mĂȘme noyau de l’hĂŽte.

  2. Namespaces :
    Introduits en 2002, ils permettent d’isoler les processus en crĂ©ant des environnements virtuels distincts. Par exemple, un conteneur peut avoir son propre espace rĂ©seau, son systĂšme de fichiers et ses processus, limitant ainsi l’interaction avec d’autres conteneurs.

  3. Cgroups (Control Groups) :
    Introduits en 2006, ils permettent de restreindre l’accĂšs Ă  certaines ressources (CPU, mĂ©moire, I/O, etc.) pour chaque conteneur. Cela garantit que les conteneurs ne consomment pas plus de ressources que prĂ©vu, Ă©vitant ainsi que des applications malveillantes ou dĂ©faillantes n’affectent les autres.

Évolution de l’hĂ©bergement des applications

  • Avant : Chaque application nĂ©cessitait une machine physique dĂ©diĂ©e. Cela Ă©tait coĂ»teux et inefficace.
  • Ensuite : L’introduction des machines virtuelles a permis d’hĂ©berger plusieurs applications sur une mĂȘme machine, mais cela nĂ©cessitait beaucoup de ressources pour chaque VM, notamment en termes de CPU et de mĂ©moire.
  • Maintenant : Avec les conteneurs, il est possible d’installer un moteur d’isolation sur une seule machine pour lancer plusieurs applications indĂ©pendamment, tout en utilisant efficacement les ressources disponibles.

Remarque: Les conteneurs reposent sur le noyau de leur hĂŽte, pour ce mĂ©canisme d’isolation des processus et donc pour certaines fonctions, ils n’ont pas de noyau propre.

Image Docker

conteneur-image

Une image Docker est un paquet autonome qui contient tout le nĂ©cessaire pour exĂ©cuter une application. Elle sert de modĂšle pour crĂ©er des conteneurs, qui sont des instances en cours d’exĂ©cution de cette image.

Une image Docker comprend :

  • Le code source de l’application
  • Les dĂ©pendances requises
  • Une version spĂ©cifique de Python (ou d’un autre environnement)
  • Le systĂšme de fichiers et les configurations nĂ©cessaires

On peut considĂ©rer l’image Docker comme un modĂšle figĂ© qui facilite le dĂ©ploiement d’un environnement de travail prĂȘt Ă  l’emploi, sans configuration manuelle.

Pour illustrer cette notion, on peut faire une analogie avec la cuisine :

  • Une image Docker est comme une recette de cuisine, dĂ©finissant les ingrĂ©dients et les Ă©tapes Ă  suivre.
  • Un conteneur reprĂ©sente le plat prĂ©parĂ© Ă  partir de cette recette, c’est-Ă -dire l’exĂ©cution concrĂšte de l’image.

Une image sert de modĂšle ou de plan pour crĂ©er un environnement d’exĂ©cution. Cela signifie qu’elle contient tout ce dont un logiciel a besoin pour fonctionner correctement, comme le systĂšme d’exploitation, les bibliothĂšques et les dĂ©pendances. Quand on utilise cette image, on peut facilement dĂ©ployer un environnement de travail qui est prĂȘt Ă  l’emploi, sans avoir Ă  configurer chaque Ă©lĂ©ment manuellement.

autre

Pour information, on manipule des images que l’on peut partager sur des registres d’image. Le plus connu et le plus classique (Ă©quivalent a Pypi pour docker) est dockerhub: https://hub.docker.com/.

Pour aller plus loin :
Les images Docker

Dockerfile

La construction des images se fait en couches (layers) : imagine chaque image comme une couche d’un gĂąteau, oĂč certaines couches peuvent ĂȘtre considĂ©rĂ©es comme “parents” et d’autres comme “enfants”. Cela signifie qu’une image peut ĂȘtre basĂ©e sur une autre, crĂ©ant ainsi une hiĂ©rarchie. Par exemple, une image parent peut contenir des configurations ou des bibliothĂšques de base, tandis que les images enfants ajoutent des fonctionnalitĂ©s spĂ©cifiques.

Pour dĂ©finir la recette menant Ă  un environnement Ă  partir d’une installation Linux de base, similaire Ă  un poste sans aucune configuration, Docker permet de crĂ©er un fichier appelĂ© Dockerfile.

Voici un exemple de Dockerfile pour un environnement Python basé sur Ubuntu 22.04 :

# On part d'un environnement Ubuntu 22.04
FROM ubuntu:22.04
# On installe Python et pip
RUN apt-get update && apt-get install -y python3-pip
# On copie les fichiers de notre projet dans l'environnement
COPY . .
# On installe les dépendances à partir du fichier requirements.txt
RUN pip install -r requirements.txt
# On définit la commande à exécuter pour lancer notre application
ENTRYPOINT ["python", "main.py"]

Le Dockerfile est un fichier texte avec une syntaxe spĂ©cifique qui permet de construire des images Docker. Il dĂ©crit l’ensemble des opĂ©rations Ă  effectuer sur l’environnement de build, incluant la personnalisation de l’environnement de base (avec la commande FROM) et les paramĂštres de lancement. Par dĂ©faut, il est courant de dĂ©finir l’ENTRYPOINT dans le Dockerfile, ce qui dĂ©termine la commande Ă  exĂ©cuter lors du dĂ©marrage du conteneur.

Remarque : Dans le monde des conteneurs, tout est un processus, et chaque processus doit ĂȘtre conçu sans Ă©tat interne. Cela signifie que les conteneurs ne doivent pas stocker d’informations qui pourraient ĂȘtre perdues lorsque le conteneur est arrĂȘtĂ© ou redĂ©marrĂ©. Par consĂ©quent, il est recommandĂ© de concevoir des applications conteneurisĂ©es de maniĂšre Ă  ce qu’elles puissent fonctionner sans dĂ©pendre d’un Ă©tat persistant.

Quelques commandes

dockerfile

Lancement d’une image

Pour exécuter une image Docker, utilisez la commande suivante :

docker run <image> <options>

Exemples :

Pour exĂ©cuter l’image hello-world :

docker run hello-world

Pour lancer une instance de PostgreSQL en arriÚre-plan avec une base de données locale, vous pouvez utiliser :

docker run -d postgres -p 5432:5432

Dans cet exemple, l’option -d permet de lancer le conteneur en arriĂšre-plan, tandis que -p 5432:5432 rend PostgreSQL accessible sur localhost:5432.

CrĂ©ation d’une image Ă  partir d’un Dockerfile

Pour construire une image Docker Ă  partir d’un Dockerfile, utilisez la commande suivante :

docker build -t <nomdelimage:versiondelimage> <cheminversledossiercontenantdockerfile>

Exemple :

Pour créer une image nommée openfoodapi avec la version 1.0.0, exécutez :

docker build -t openfoodapi:1.0.0 .

Ici, le point . indique que le Dockerfile se trouve à la racine du répertoire courant.

Déploiement

Pour dĂ©ployer une image sur un registre d’images, comme DockerHub, vous devez suivre ces Ă©tapes :

  • Avoir un compte valide sur DockerHub.
  • Vous connecter en ligne de commande Ă  DockerHub via l’outil Docker.
  • Ajouter un tag Ă  l’image pour spĂ©cifier le chemin vers le registre de destination.

Pour plus d’informations, consultez la documentation de Docker.

Travaux Pratiques

L’objectif de ce TP est de crĂ©er une image Docker pour un projet fonctionnel, tel que votre propre projet.

À partir d’un projet fonctionnel, vous pouvez dĂ©finir une image Docker pour l’exĂ©cuter dans un environnement isolĂ© :

  1. Installez Docker en suivant les instructions disponibles ici.
  2. VĂ©rifiez que l’installation a rĂ©ussi en exĂ©cutant la commande suivante : docker run hello-world.
  3. CrĂ©ez un fichier Dockerfile et essayez de construire localement l’image Python en utilisant la commande : docker build -t monimage ..
  4. Taguez votre image et publiez-la en suivant le tutoriel mentionné précédemment.
  5. Mettez en place l’automatisation via GitHub Actions en consultant cette ressource : https://github.com/marketplace/actions/build-and-push-docker-images.