Introduction aux conteneurs et à Docker
1. Concepts autours des conteneurs
La mise en conteneur est une approche de développement de logiciels qui consiste à empaqueter une application ou un service, ses dépendances et sa configuration (extraits sous forme de fichiers manifeste de déploiement) sous forme d’image de conteneur. L’application en conteneur peut être testée en tant qu’unité et déployée sous forme d’instance d’image de conteneur sur le système d’exploitation (SE) hôte.
De la même manière que les conteneurs de transport permettent de transporter des marchandises par bateau, par train ou par camion indépendamment de la nature de la cargaison, les conteneurs logiciels agissent comme une unité de déploiement logiciel standard qui peut contenir du code et des dépendances différents. Cette façon de mettre les logiciels en conteneur permet aux développeurs et aux informaticiens de les déployer dans les environnements avec peu ou pas de modifications.
Par ailleurs, les conteneurs isolent les applications les unes des autres sur un SE partagé. Les applications en conteneur s’exécutent sur un hôte de conteneurs qui à son tour s’exécute sur le SE (Linux ou Windows). Par conséquent, les conteneurs ont un encombrement bien moindre que les images de machine virtuelle.
Chaque conteneur peut exécuter une application web ou un service dans son intégralité, comme l’illustre la figure 1-1. Dans cet exemple, l’hôte Docker est un hôte de conteneurs, et App1, App2, Svc 1 et Svc 2 sont des applications ou des services en conteneur.
Figure 1-1 : plusieurs conteneurs s’exécutant sur un hôte de conteneurs
L’autre avantage de la mise en conteneur est l’extensibilité. Vous pouvez rapidement monter en charge en créant des conteneurs pour des tâches à court terme. Du point de vue de l’application, instancier une image (c.-à-d., créer un conteneur) revient à instancier un processus comme un service ou une application web. Cependant, dans un souci de fiabilité, quand il s’agit d’exécuter plusieurs instances d’une même image sur plusieurs serveurs hôtes, il est en principe préférable que chaque conteneur (instance d’image) s’exécute sur un serveur hôte différent ou sur une machine virtuelle dans différents domaines d’erreur.
Pour résumer, les conteneurs offrent les avantages de l’isolation, de la portabilité, de l’agilité, de l’extensibilité et du contrôle dans l’ensemble du flux de travail du cycle de vie de l’application. L’avantage le plus important est l’isolation de l’environnement fourni entre le développement et les opérations.
2. Qu’est-ce que Docker ?
Docker est un projet open source permettant d’automatiser le déploiement d’applications en tant que conteneurs portables et autonomes exécutables sur le cloud ou localement. Docker est également une entreprise qui développe et diffuse cette technologie, en collaboration avec des fournisseurs de services cloud, Linux et Windows, notamment Microsoft.

Figure 1-2 : Docker déploie des conteneurs dans toutes les couches du cloud hybride.
Les conteneurs Docker peuvent s’exécuter n’importe où, en local dans le centre de données client, dans un fournisseur de services externe ou dans le cloud, sur Azure. Les conteneurs d’images Docker peuvent s’exécuter en mode natif sur Linux et Windows. Toutefois, les images Windows peuvent s’exécuter uniquement sur des hôtes Windows et les images Linux peuvent s’exécuter sur des hôtes Linux et des hôtes Windows (à l’aide d’une machine virtuelle Linux Hyper-V, jusqu’à présent), où le terme « hôte » désigne un serveur ou une machine virtuelle.
Les développeurs peuvent utiliser des environnements de développement sur Windows, Linux ou macOS. Sur l’ordinateur de développement, le développeur exécute un hôte Docker sur lequel sont déployées les images Docker, y compris l’application et ses dépendances. Les développeurs qui travaillent sur Linux ou sur macOS utilisent un hôte Docker basé sur Linux et peuvent créer des images uniquement pour les conteneurs Linux. (Les développeurs travaillant sur macOS peuvent modifier du code ou exécuter l’interface de ligne de commande Docker à partir de macOS, mais à partir du moment de cette écriture, les conteneurs ne s’exécutent pas directement sur macOS.) Les développeurs qui travaillent sur Windows peuvent créer des images pour des conteneurs Linux ou Windows.
Pour héberger des conteneurs dans des environnements de développement et fournir des outils de développement supplémentaires, Docker fournit Docker Desktop pour Windows ou pour macOS. Ces produits installent la machine virtuelle nécessaire (l’hôte Docker) pour héberger les conteneurs.
3. Comparaison entre les conteneurs Docker et les machines virtuelles

Figure 1-3 : Comparaison entre les machines virtuelles traditionnelles et les conteneurs Docker
Pour les machines virtuelles, il existe trois couches de base dans le serveur hôte, de bas en haut : infrastructure, système d’exploitation hôte et un hyperviseur, et par-dessus chaque machine virtuelle a son propre système d’exploitation et toutes les bibliothèques nécessaires. Pour Docker, le serveur hôte comprend uniquement l’infrastructure et le système d’exploitation, et par-dessus, le moteur de conteneur, qui conserve le conteneur isolé tout en partageant les services de système d’exploitation de base.
Du fait que les conteneurs nécessitent beaucoup moins de ressources (par exemple, ils n’ont pas besoin d’un système d’exploitation complet), leur démarrage est rapide et leur déploiement est simple. Cela vous permet d’avoir une densité plus élevée, ce qui vous permet d’exécuter plus de services sur la même unité matérielle, limitant les coûts.
Comme effet secondaire de l’exécution sur le même noyau, vous obtenez une moins bonne isolation que sur les machines virtuelles.
L’objectif principal d’une image est de garantir un environnement (dépendances) identique entre les différents déploiements. Vous pouvez ainsi la déboguer sur votre machine et la déployer sur une autre machine en étant sûr de garder le même environnement.
Une image conteneur est un moyen d’empaqueter une application ou un service et de les déployer ensuite d’une façon fiable et reproductible. Plus qu’une simple technologie, Docker peut également être vu comme une philosophie et un processus.
Lorsque vous utilisez Docker, vous n’entendez pas les développeurs dire : « Cela fonctionne sur mon ordinateur, pourquoi pas en production ? » Ils peuvent simplement dire, « Ça s’exécute sur Docker », car l’application Docker packagée peut être exécutée sur n’importe quel environnement Docker pris en charge, et elle s’exécute comme prévu sur toutes les cibles de déploiement (telles que le développement, l’assurance qualité, la préproduction et la production).
4. Terminologie Docker
Nous allons lister ici les termes et les définitions que vous devez connaître avant d’explorer Docker de manière plus approfondie. Pour obtenir d’autres définitions, consultez le glossaire complet fourni par Docker.
Image conteneur (container image) : package de toutes les dépendances et informations nécessaires pour créer un conteneur. Une image inclut toutes les dépendances (notamment les frameworks) ainsi que la configuration de déploiement et d’exécution à utiliser par le runtime du conteneur. En règle générale, une image est dérivée de plusieurs images de base qui sont empilées en couches pour former le système de fichiers du conteneur. Une image est immuable une fois qu’elle a été créée.
Dockerfile : fichier texte contenant des instructions pour la création d’une image Docker. C’est comme un script de commandes, la première ligne indique l’image de base avec laquelle commencer, puis suivent les instructions pour installer les programmes requis, copier les fichiers, etc. jusqu’à obtenir l’environnement de travail dont vous avez besoin.
Création (build) : action de créer une image conteneur sur la base des informations et du contexte fournis par le fichier Dockerfile associé, plus des fichiers supplémentaires dans le dossier où l’image est créée. Vous pouvez générer des images avec la commande Docker suivante :
docker build
Conteneur (container) : instance d’une image Docker. Un conteneur représente l’exécution d’une application, d’un processus ou d’un service. Il renferme une image Docker, un environnement d’exécution et un ensemble standard d’instructions. Pour mettre un service à l’échelle, vous créez plusieurs instances d’un conteneur à partir de la même image. Cela peut également être fait par un traitement par lots, qui passe des paramètres différents à chaque instance.
Volumes : offre un système de fichiers accessible en écriture que le conteneur peut utiliser. Dans la mesure où les images sont en lecture seule, mais que la plupart des programmes ont besoin d’écrire dans le système de fichiers, les volumes ajoutent une couche accessible en écriture, par-dessus l’image de conteneur, afin que les programmes aient accès à un système de fichiers accessible en écriture. Le programme ne sait pas qu’il accède à un système de fichiers en couches, il s’agit simplement du système de fichiers normal. Les volumes résident dans le système hôte et sont gérés par Docker.
Balise (tag) : marque ou étiquette que vous pouvez appliquer aux images pour identifier les différentes images ou versions de l’image initiale (selon le numéro de version de l’environnement cible).
Build en plusieurs étapes : fonctionnalité, depuis Docker 17.05 ou une version ultérieure, qui permet de réduire la taille des images finales. Par exemple, une image de base volumineuse, contenant le Kit de développement logiciel (SDK) peut être utilisée pour la compilation et la publication, puis une petite image de base de runtime uniquement peut être utilisée pour héberger l’application.
Dépôt (repository) : collection d’images Docker associées, identifiées par une balise qui indique la version de chaque image. Certains dépôts contiennent plusieurs variantes d’une image spécifique, par exemple une image contenant des SDK (plus lourde), une image contenant uniquement des runtimes (plus légère), etc. Ces variantes peuvent être identifiées par des balises. Un dépôt peut contenir des variantes de plateforme, comme une image Linux et une image Windows.
Registre (registry) : service qui fournit l’accès aux dépôts. Le registre par défaut utilisé pour la plupart des images publiques est Docker Hub (propriété de l’organisation Docker). Un registre contient généralement des dépôts de plusieurs équipes. Les entreprises utilisent souvent des registres privés pour stocker et gérer les images qu’elles ont créées. Azure Container Registry est un autre exemple de registre.
Image multi-arch : pour la multi-architecture, cette fonctionnalité simplifie la sélection de l’image appropriée, en fonction de la plateforme où Docker est en cours d’exécution. Par exemple, quand un fichier Docker demande une image de base FROM mcr.microsoft.com/dotnet/sdk:6.0 à partir du Registre, il obtient en fait 6.0-nanoserver-20H2, 6.0-nanoserver-1809 ou 6.0-bullseye-slim, selon le système d’exploitation et la version où Docker est en cours d’exécution.
Docker Hub : registre public dans lequel vous pouvez charger et manipuler des images. Docker Hub fournit un hébergement d’images Docker, des registres publics ou privés, des déclencheurs de build et des webhooks, et l’intégration avec GitHub et Bitbucket.
Docker Trusted Registry (DTR) : service de registre Docker (fourni par Docker) qui peut être installé en local pour résider au sein même du centre de données et du réseau de l’organisation. Il est pratique pour les images privées devant être gérées en interne dans l’entreprise. Docker Trusted Registry est intégré au produit Docker Datacenter.
Docker Desktop : outils de développement pour Windows et macOS permettant de créer, d’exécuter et de tester des conteneurs localement. Docker Desktop pour Windows fournit des environnements de développement pour les conteneurs Linux et Windows. L’hôte Linux Docker sur Windows est basé sur une machine virtuelle Hyper-V. L’hôte pour les conteneurs Windows est directement basé sur Windows. Docker Desktop pour Mac est basé sur l’infrastructure Apple Hypervisor et l’hyperviseur xhyve, qui fournit une machine virtuelle hôte Docker Linux sur macOS. Docker Desktop pour Windows et Mac remplace la boîte à outils Docker, qui était basée sur Oracle VirtualBox.
Compose : outil en ligne de commande et format de fichier YAML fournissant des métadonnées pour la définition et l’exécution d’applications multiconteneurs. Vous définissez une application basée sur plusieurs images avec un ou plusieurs fichiers .yml qui peuvent remplacer les valeurs en fonction de l’environnement. Après avoir créé les définitions, vous déployez l’application multiconteneur entière à l’aide d’une seule commande (docker-compose up) qui crée un conteneur par image sur l’hôte Docker.
Cluster : collection d’hôtes Docker exposés en tant qu’hôte Docker virtuel unique, ce qui permet la mise à l’échelle de l’application en fonction du nombre d’instances des services répartis entre les différents hôtes au sein du cluster. Vous pouvez créer des clusters Docker avec Kubernetes, Amazon EKS, Azure Service Fabric, Docker Swarm et Mesosphere DC/OS.
Orchestrator : outil qui simplifie la gestion des clusters et des hôtes Docker. Les orchestrateurs vous permettent de gérer les images, les conteneurs et les hôtes à l’aide d’une interface de ligne de commande (CLI) ou d’une interface graphique utilisateur. Vous pouvez gérer la mise en réseau des conteneurs, les configurations, l’équilibrage de charge, la découverte des services, la haute disponibilité, la configuration des hôtes Docker, et bien plus encore. Un orchestrateur gère l’exécution, la distribution, la mise à l’échelle et la réparation des charges de travail dans une collection de nœuds. En règle générale, les produits Orchestrator sont les mêmes produits qui fournissent l’infrastructure de cluster, comme Kubernetes, Amazon EKS et Azure Service Fabric, entre autres offres sur le marché.
5. Conteneurs, images et registres Docker
Quand un développeur utilise Docker, il crée une application ou un service, qu’il empaquette ensuite avec les dépendances associées dans une image conteneur. Une image est une représentation statique de l’application ou du service, de leur configuration et de leurs dépendances.
Pour exécuter l’application ou le service, l’image de l’application est instanciée, créant ainsi un conteneur à exécuter sur l’hôte Docker. Les conteneurs sont initialement testés sur une machine ou un environnement de développement.
Les développeurs doivent stocker les images dans un registre, comparable à une bibliothèque d’images, qui est utilisé pour le déploiement sur des orchestrateurs de production. Docker gère un registre public via Docker Hub. D’autres fournisseurs proposent des registres pour différentes collections d’images, notamment Amazon ECR ou Azure Container Registry. Les entreprises peuvent également gérer un registre privé local pour stocker leurs propres images Docker.

Figure 1-4 : Taxonomie des termes et concepts Docker
le registre est semblable à une bibliothèque où les images sont stockées et peuvent être extraites pour générer des conteneurs afin d’exécuter les services ou les applications web. Il existe des registres Docker privés en local et sur le cloud public. Docker Hub est un registre public géré par Docker, tout comme Docker Trusted Registry, une solution de classe d’entreprise, Azure propose Azure Container Registry. AWS, Google et d’autres ont également des registres de conteneurs.
Placer des images dans un registre vous permet de stocker les bits d’application statiques et immuables, y compris toutes les dépendances au niveau du framework. Ces images peuvent ensuite être versionnées et déployées dans différents environnements, offrant ainsi une unité de déploiement cohérente.
L’utilisation de registres d’images privés, hébergés localement ou dans le cloud, est recommandée dans les situations suivantes :
-
Vous ne voulez pas partager vos images publiquement pour des raisons de confidentialité.
-
Vous souhaitez limiter la latence du réseau entre vos images et l’environnement de déploiement choisi. Par exemple, si votre environnement de production est le cloud Azure, vous souhaiterez probablement stocker vos images dans Azure Container Registry pour réduire au maximum la latence du réseau. De la même manière, si votre environnement de production est local, vous souhaiterez peut-être disposer d’un service Docker Trusted Registry local dans le même réseau local.
6. Docker Compose
Docker Compose est un outil destiné à définir et exécuter des applications Docker à plusieurs conteneurs. Dans Compose, vous utilisez un fichier YAML pour configurer les services de votre application. Ensuite, vous créez et vous démarrez tous les services à partir de votre configuration en utilisant une seule commande.
6. Les commandes de base pour Docker et Docker Compose
Commandes de monitoring
Les commandes suivantes sont, les premières que vous avez besoin de connaître quand vous utilisez Docker.
docker ps (-a)
docker ps vous affiche toutes les containers de docker qui tournent actuellement sur votre environnement. Si vous ajoutez l’option -a, alors vous verrez mêmes les containers stoppés.
docker-compose ps
docker-compose ps affiche tous les containers qui ont été lancés par docker-compose (qu’ils tournent actuellement ou non).
docker images
docker-compose images
Ces commandes vous permettent de voir les images Docker actuellement disponible sur votre environnement.
docker network ls
La commande docker network ls liste les différents réseaux
Commandes de runtime
Les commandes suivantes vont vous permettre de gerer vos instances/containers Docker
docker-compose up (-d) (--build)
docker-compose stop
La docker-compose est la plus simple car vous n’avez besoin que de 2 commandes : up et stop. stop est assez explicite et stop (mais ne supprime pas) vos conteneurs, mais up nécessite plus d’explications : cela va construire vos images si elles ne le sont pas déjà, et va démarrer vos dockers.
Si vous voulez re-build vos images, utilisez l’option --build (vous pouvez aussi utiliser la commande docker-compose build pour uniquement construire des images). L’option -d, qui signifie "detach" fait tourner les conteneurs en tâche de fond.
docker build (-t NAME ) PATH /URL
Avec Docker, vous avez besoin d’une commande séparée pour construire votre image, où vous pouvez spécifier le nom de votre image et vous devez spécifier le PATH ou URL selon votre contexte (cela peut être un repo git).
docker build (-t NAME ) PATH /URL
Avec Docker, vous avez besoin d’une commande séparée pour construire votre image, où vous pouvez spécifier le nom de votre image et vous devez spécifier le PATH ou URL selon votre contexte (cela peut être un repo git).
docker run (-d) (-p hostPort :containerPort ) (--name NAME ) IMGNAME /IMGID
run crée le conteneur en utilisant l’image que vous indiquez. Vous pouvez spécifier de nombreux paramètres. Nous vous recommandons d’ajouter un nom à votre conteneur et vous pourriez avoir besoin de spécifier quelques ports à exposer. Comme pour docker-compose, le -d lance le conteneur en tâche de fond.
docker start ID /NAME
docker stop ID /NAME
Le start and stop ne devraient pas être trop compliqués à comprendre, mais il faut noter que vous pouvez “start” uniquement des conteneurs qui sont déjà arrêtés, donc déjà build avec la commande run.
docker exec -it NAME /ID “sh” /”/bin/bash”
Cette commande vous permet de lancer un shell sur votre container. Je préfère utiliser "/bin/bash" mais votre conteneur peut ne pas avoir bash d’installé, et seulement “sh” qui est plus courant (surtout sur les alpines). Si vous avez des configurations spéciales dans votre conteneur, vous aurez peut-être besoin d’utiliser des arguments supplémentaires pour vous y connecter. Cette commande peut vous permettre de faire bien plus, je vous recommande donc de lire cette doc pour trouver des informations supplémentaires..
Commandes de suppression
Ces commandes permettent de supprimer vos conteneurs et vos images. Vous en aurez probablement besoin pour libérer de l’espace disque.
docker rm ID /NAME
docker-compose rm
Le docker rm supprime seulement un conteneur alors que docker-compose rm supprime tous les conteneurs démarrés avec une commande docker-compose.
docker rmi ID /NAME
Docker rmi supprime l’image que vous passez en paramètre et récursivement toutes les images intermédiaires utilisées pour la construire.
Commandes de logs
Les commandes suivantes sont utiles quand vous devez débugger certains de vos conteneurs (ou, plus souvent, l'application que vous déployez à l’intérieur).
docker logs ID /NAME (-f --tail NBLINE )
Cette commande affiche les logs du container passé en paramètre. Si vous utilisez l’option -f --tail NBLINE vous pouvez suivre en live le flux de vos logs (NBLINE est le nombre de lignes que vous souhaitez afficher). Gardez à l’esprit de choisir un nombre de lignes que vous serez capable de gérer, pour ne pas être dépassé par vos logs.
docker-compose logs (ID /NAME )
L’option (ID /NAME ) avec docker-compose logs vous permet de voir les logs d’un conteneur uniquement, au lieu de voir tous les logs. L’astuce ici est que si vous n’utilisez pas l’option -d quand vous utilisez docker run ou docker-compose up vous verrez vos logs directement (mais vous aurez besoin d’arrêter le conteneur pour quitter la vue). Cela peut toujours être utile pour débugger des applications au démarrage.