Skip to content

Conteneurisation avec Docker

Avant-propos

« Ça marche sur ma machine » est l'excuse la plus classique des développeurs. Docker fait disparaître cette excuse pour de bon. La technologie de conteneurisation empaquette une application et toutes ses dépendances dans une unité standardisée, garantissant un fonctionnement cohérent dans tout environnement. C'est la pierre angulaire de la livraison logicielle moderne.

Que allez-vous apprendre dans cet article ?

À l'issue de ce chapitre, vous maîtriserez :

  • Concepts fondamentaux : comprendre les trois concepts clés : image, conteneur et registre
  • Comparaison d'architectures : comprendre la différence essentielle entre conteneurs et machines virtuelles
  • Compétences pratiques : maîtriser l'écriture de Dockerfiles et les commandes courantes
  • Bases de l'orchestration : apprendre à gérer des applications multi-services avec Docker Compose
  • Bonnes pratiques : connaître l'optimisation d'images, le durcissement de sécurité et autres pratiques de production
ChapitreContenuConcepts clés
Chapitre 1Pourquoi les conteneursCohérence d'environnement, efficacité des ressources, livraison standardisée
Chapitre 2Concepts fondamentauxImage, conteneur, registre, Dockerfile
Chapitre 3Cycle de vie DockerÉcrire, construire, pousser, exécuter, gérer
Chapitre 4Docker ComposeOrchestration multi-services, réseau, volumes de données
Chapitre 5Bonnes pratiquesOptimisation d'images, sécurité, construction multi-étapes

1. Pourquoi les conteneurs ?

Avant l'apparition des conteneurs, déployer une application nécessitait d'installer manuellement l'environnement d'exécution sur le serveur, de configurer les variables d'environnement et de gérer les conflits de dépendances. Les différences entre environnements (développement, test, production) étaient un terreau fertile pour les bugs.

Virtual Machines vs Containers
Switch between both virtualization models to compare their architecture
App A / App B / App C
App A + Bins/Libs
App B + Bins/Libs
App C + Bins/Libs
Docker Engine
Host OS
Physical hardware
Startup speedSeconds
Resource usageShared host OS kernel (MB scale)
IsolationProcess-level isolation
DensityHundreds of containers per host
Image sizeMB scale

Quels problèmes les conteneurs résolvent-ils ?

ProblèmeApproche traditionnelleApproche conteneurisée
Incohérence d'environnement« Ça marche chez moi »Empaquetage de toutes les dépendances, cohérence partout
Conflits de dépendancesL'App A nécessite Node 14, l'App B Node 18Chaque conteneur dispose d'un environnement isolé
Gaspillage de ressourcesChaque VM nécessite un OS completPartage du noyau, surcoût de l'ordre du Mo
Déploiement lentInstallation et configuration manuellesUne seule commande docker run
Mise à l'échelle difficileCréer une VM, installer l'environnement, déployerDémarrage de nouveaux conteneurs en quelques secondes

La nature d'un conteneur

Un conteneur n'est pas une machine virtuelle légère. Sa nature est celle d'un processus isolé. Le noyau Linux réalise la conteneurisation via deux mécanismes :

  • Namespaces : isolent la visibilité des processus (PID, réseau, système de fichiers, etc.)
  • Cgroups : limitent l'utilisation des ressources des processus (CPU, mémoire, E/S)

Les processus dans un conteneur ne sont fondamentalement pas différents des processus ordinaires sur la machine hôte — ils sont simplement « enfermés dans une pièce sans vue sur l'extérieur ».


2. Concepts fondamentaux

L'univers de Docker s'articule autour de trois concepts clés : l'image (Image), le conteneur (Container) et le registre (Registry).

ConceptAnalogieDescription
Image (Image)Classe / ModèleModèle d'application en lecture seule, contenant le code, l'environnement d'exécution, les bibliothèques et la configuration
Conteneur (Container)Instance / ObjetInstance d'exécution d'une image, en lecture-écriture, dotée d'un cycle de vie indépendant
Registre (Registry)App StoreService de stockage et de distribution d'images (Docker Hub, ACR, ECR)
DockerfileRecette / PlanFichier texte définissant comment construire une image
Volume de données (Volume)Disque dur externePersistance des données, qui survivent à la suppression du conteneur

Structure en couches d'une image

Les images Docker sont composées de plusieurs couches en lecture seule (Layer), chaque instruction du Dockerfile créant une couche :

┌─────────────────────────┐
│  CMD ["node", "app.js"] │  ← Couche de commande de démarrage
├─────────────────────────┤
│  COPY . /app            │  ← Couche de code applicatif (change souvent)
├─────────────────────────┤
│  RUN npm install        │  ← Couche d'installation des dépendances (change occasionnellement)
├─────────────────────────┤
│  FROM node:18-alpine    │  ← Couche d'image de base (change rarement)
└─────────────────────────┘

Pourquoi la structure en couches est-elle importante ?

Docker met en cache chaque couche. Si une couche n'a pas changé, la construction réutilise directement le cache. C'est pourquoi il convient de placer les instructions à faible fréquence de changement en premier (comme l'installation des dépendances) et celles à haute fréquence de changement en dernier (comme la copie du code). Ainsi, la plupart des constructions bénéficient du cache et sont beaucoup plus rapides.


3. Cycle de vie Docker

De l'écriture du Dockerfile à l'exécution du conteneur, le flux de travail de Docker est un pipeline clair et bien défini.

Docker Lifecycle
Click each stage to inspect the details
📝
Write a Dockerfile
🔨
Build the image
☁️
Push to registry
▶️
Run the container
⚙️
Manage containers
Write a Dockerfile
A Dockerfile is the recipe for building an image. It starts from a base image and defines how to assemble the application environment step by step. Each instruction creates an image layer that Docker can cache for later builds.
Common commands
FROM node:18-alpineChoose the base image
WORKDIR /appSet the working directory
COPY package*.json ./Copy dependency files for cache reuse
RUN npm installInstall dependencies
COPY . .Copy application code
EXPOSE 3000Declare the port
CMD ["node", "server.js"]Start command

Aide-mémoire des instructions Dockerfile courantes

InstructionRôleExemple
FROMSpécifier l'image de baseFROM node:18-alpine
WORKDIRDéfinir le répertoire de travailWORKDIR /app
COPYCopier des fichiers dans l'imageCOPY package.json ./
RUNExécuter des commandes lors de la constructionRUN npm install
ENVDéfinir des variables d'environnementENV NODE_ENV=production
EXPOSEDéclarer un port (uniquement documentaire)EXPOSE 3000
CMDCommande de démarrage du conteneurCMD ["node", "app.js"]
ENTRYPOINTPoint d'entrée du conteneur (difficile à surcharger)ENTRYPOINT ["nginx"]

4. Docker Compose : orchestration multi-services

Un projet réel comporte généralement plusieurs conteneurs. Une application web peut nécessiter : un serveur d'application + une base de données + Redis + Nginx. Docker Compose permet de définir et gérer plusieurs conteneurs dans un seul fichier YAML.

Exemple de docker-compose.yml

yaml
version: '3.8'
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DB_HOST=db
      - REDIS_HOST=redis
    depends_on:
      - db
      - redis

  db:
    image: postgres:15-alpine
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=secret

  redis:
    image: redis:7-alpine

volumes:
  db-data:

Concepts clés de Compose

ConceptDescriptionExemple
servicesDéfinit chaque service de conteneurapp, db, redis
volumesVolumes de données persistantsdb-data conserve les fichiers de la base de données
networksRéseau personnalisé (créé automatiquement par défaut)Les services communiquent entre eux via le nom du service
depends_onDépendances d'ordre de démarrageapp dépend de db et redis
environmentVariables d'environnementMot de passe de la base de données, adresse de connexion

Découverte de services

Dans Docker Compose, le nom du service est le nom d'hôte. Le conteneur app peut accéder directement à la base de données via db:5432 et à Redis via redis:6379, sans avoir besoin de connaître les adresses IP. C'est grâce au DNS intégré de Docker.


5. Bonnes pratiques

5.1 Construction multi-étapes (Multi-stage Build)

La construction multi-étapes est un outil puissant pour optimiser la taille des images. L'étape de construction installe tous les outils et dépendances, l'étape finale ne conserve que les fichiers nécessaires à l'exécution.

dockerfile
# Étape de construction
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Étape d'exécution
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]

5.2 Liste de contrôle pour l'optimisation des images

Élément d'optimisationApprocheEffet
Choisir une image de base légèreUtiliser alpine plutôt que ubuntuImage réduite de ~200 Mo à ~50 Mo
Fusionner les instructions RUNConnecter plusieurs commandes avec &&Réduire le nombre de couches
Utiliser .dockerignoreExclure node_modules, .git, etc.Accélérer la construction, réduire le contexte
Construction multi-étapesSéparer les environnements de construction et d'exécutionL'image finale ne contient pas les outils de construction
Fixer les numéros de versionnode:18.17-alpine plutôt que node:latestConstructions reproductibles

5.3 Pratiques de sécurité

PratiqueDescription
Ne pas exécuter en rootUSER node pour spécifier un utilisateur non-root
Scanner les vulnérabilitésdocker scout ou Trivy pour scanner les images
Privilèges minimauxN'installer que les paquets nécessaires, pas d'outils de débogage
Ne pas coder les secrets en durUtiliser des variables d'environnement ou Docker Secrets
Mettre à jour régulièrement les images de baseCorriger les vulnérabilités de sécurité rapidement

Résumé

La conteneurisation Docker est l'infrastructure de la livraison logicielle moderne. La comprendre est essentielle pour tout développeur.

Passons en revue les points clés de ce chapitre :

  1. Conteneurs vs machines virtuelles : les conteneurs partagent le noyau hôte, ils sont plus légers et plus rapides, mais l'isolation est légèrement inférieure à celle des VM
  2. Les trois éléments fondamentaux : image (modèle), conteneur (instance), registre (distribution)
  3. Dockerfile : construction en couches, tirer parti du cache, instructions peu changeantes en premier
  4. Docker Compose : définir des applications multi-services en YAML, le nom du service est le nom d'hôte
  5. Pratiques de production : construction multi-étapes pour réduire la taille de l'image, image de base alpine, exécution en non-root

Pour aller plus loin