Docker pour les développeurs : Conteneurs, Images et Compose
· 12 min de lecture
Table des matières
- Comprendre Docker : Pourquoi c'est important
- Concepts fondamentaux expliqués
- Anatomie et structure d'un Dockerfile
- Meilleures pratiques pour les Dockerfiles
- Commandes Docker essentielles
- Docker Compose pour les applications multi-conteneurs
- Flux de travail de développement et conseils
- Débogage et dépannage
- Considérations de sécurité
- Optimisation des performances
- Questions fréquemment posées
- Articles connexes
Comprendre Docker : Pourquoi c'est important
Docker a fondamentalement changé la façon dont les développeurs construisent, livrent et exécutent des applications. Avant Docker, la configuration des environnements de développement était un cauchemar de conflits de dépendances, d'incompatibilités de versions et du fameux problème « ça marche sur ma machine ».
Docker résout ce problème en empaquetant votre application avec tout ce dont elle a besoin pour fonctionner — code, environnement d'exécution, outils système, bibliothèques et paramètres — dans une unité standardisée appelée conteneur. Ce conteneur s'exécute de manière identique sur votre ordinateur portable, la machine de votre collègue et les serveurs de production.
Les avantages sont immédiats et tangibles :
- Cohérence : Les environnements de développement, de staging et de production sont identiques
- Isolation : Chaque application s'exécute dans son propre conteneur sans conflits
- Portabilité : Les conteneurs s'exécutent partout où Docker est installé
- Efficacité : Les conteneurs partagent le noyau du système d'exploitation hôte, utilisant beaucoup moins de ressources que les machines virtuelles
- Rapidité : Les conteneurs démarrent en quelques secondes, pas en minutes
Pour les développeurs, Docker signifie que vous pouvez démarrer une pile d'applications complète — serveur web, base de données, cache, file d'attente de messages — avec une seule commande. Plus besoin de passer des heures à installer PostgreSQL ou à déboguer des problèmes de configuration Redis.
Concepts fondamentaux expliqués
Comprendre les concepts fondamentaux de Docker est essentiel avant de plonger dans l'utilisation pratique. Ces éléments de base fonctionnent ensemble pour créer l'écosystème Docker.
| Concept | Ce que c'est | Analogie | Caractéristiques clés |
|---|---|---|---|
| Image | Modèle en lecture seule avec app + dépendances | Une définition de classe en POO | Immuable, en couches, partageable |
| Conteneur | Instance en cours d'exécution d'une image | Un objet (instance de classe) | Isolé, éphémère, sans état |
| Dockerfile | Instructions pour construire une image | Une recette ou un plan | Fichier texte, sous contrôle de version |
| Volume | Stockage persistant en dehors du conteneur | Un disque dur externe | Survit à la suppression du conteneur |
| Réseau | Communication entre conteneurs | Un réseau local (LAN) | Isolé, configurable, sécurisé |
| Registre | Stockage pour les images (Docker Hub) | npm/PyPI pour les conteneurs | Public ou privé, versionné |
Images vs Conteneurs : La distinction critique
C'est là que de nombreux débutants se perdent. Une image est un instantané statique — considérez-la comme un modèle figé. Un conteneur est ce que vous obtenez lorsque vous exécutez cette image — c'est un processus en direct et en cours d'exécution.
Vous pouvez créer un nombre illimité de conteneurs à partir d'une seule image, tout comme vous pouvez créer plusieurs objets à partir d'une classe. Chaque conteneur est isolé des autres, même s'ils sont tous basés sur la même image.
Conseil de pro : Les images sont construites en couches. Chaque instruction dans votre Dockerfile crée une nouvelle couche. Docker met en cache ces couches, donc reconstruire une image ne reconstruit que les couches qui ont changé. Cela rend les constructions incroyablement rapides.
Volumes : Résoudre le problème de persistance
Les conteneurs sont éphémères par conception — lorsque vous supprimez un conteneur, tout ce qu'il contient disparaît. C'est excellent pour les applications sans état mais problématique pour les bases de données ou toute donnée que vous devez conserver.
Les volumes résolvent ce problème en stockant les données en dehors du système de fichiers du conteneur. Les données persistent même lorsque les conteneurs sont supprimés et recréés. Il existe trois types de montages :
- Volumes : Gérés par Docker, stockés dans la zone de stockage de Docker (recommandé)
- Montages bind : Mappent un répertoire hôte directement dans le conteneur (utile pour le développement)
- Montages tmpfs : Stockés uniquement dans la mémoire de l'hôte, jamais écrits sur le disque (pour les données sensibles)
Anatomie et structure d'un Dockerfile
Un Dockerfile est un document texte contenant des instructions pour construire une image Docker. Chaque instruction crée une couche dans l'image, et Docker met en cache ces couches pour plus d'efficacité.
Voici une répartition des instructions Dockerfile les plus courantes :
| Instruction | Objectif | Exemple | Meilleure pratique |
|---|---|---|---|
FROM |
Image de base à partir de laquelle construire | FROM node:22-alpine |
Utiliser des versions spécifiques, préférer alpine |
WORKDIR |
Définir le répertoire de travail | WORKDIR /app |
Utiliser des chemins absolus |
COPY |
Copier des fichiers de l'hôte vers l'image | COPY package.json . |
Copier d'abord les dépendances pour la mise en cache |
RUN |
Exécuter des commandes pendant la construction | RUN npm install |
Enchaîner les commandes avec && pour réduire les couches |
EXPOSE |
Documenter le port sur lequel l'app écoute | EXPOSE 3000 |
Documentation uniquement, ne publie pas le port |
ENV |
Définir des variables d'environnement | ENV NODE_ENV=production |
Utiliser pour la configuration |
USER |
Définir l'utilisateur pour les commandes suivantes | USER node |
Ne jamais exécuter en tant que root en production |
CMD |
Commande par défaut au démarrage du conteneur | CMD ["node", "server.js"] |
Utiliser le format tableau JSON |
Comprendre la mise en cache des couches
Docker construit les images couche par couche, de haut en bas. Chaque instruction crée une nouvelle couche. Si une couche n'a pas changé, Docker réutilise la version mise en cache au lieu de la reconstruire.
C'est pourquoi vous devriez structurer votre Dockerfile pour placer les instructions qui changent rarement en haut et celles qui changent fréquemment en bas. Par exemple, vos dépendances changent moins souvent que votre code source, donc installez les dépendances avant de copier les fichiers sources.
# Mauvais : Copie tout d'abord, puis installe
COPY . .
RUN npm install
# Bon : Installe d'abord les dépendances, exploite le cache
COPY package*.json ./
RUN npm install
COPY . .
Meilleures pratiques pour les Dockerfiles
Écrire des Dockerfiles efficaces est un art. Voici un exemple prêt pour la production qui démontre plusieurs meilleures pratiques :
# Construction multi-étapes : étape de construction
FROM node:22-alpine AS builder
WORKDIR /app
# Copier d'abord les fichiers de dépendances pour une meilleure mise en cache
COPY package*.json ./
RUN npm ci --production
# Copier le code source et construire
COPY . .
RUN npm run build
# Construction multi-étapes : étape de production
FROM node:22-alpine
WORKDIR /app
# Copier uniquement ce qui est nécessaire depuis le builder
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
# Sécurité : exécuter en tant qu'utilisateur non-root
USER node
# Documenter le port (ne le publie pas réellement)
EXPOSE 3000
# Vérification de santé pour l'orchestration de conteneurs
HEALTHCHECK --interval=30s --timeout=3s \
CMD node healthcheck.js || exit 1
# Démarrer l'application
CMD ["node", "dist/server.js"]
Constructions multi-étapes : Réduction spectaculaire de la taille
Les constructions multi-étapes vous permettent d'utiliser plusieurs instructions FROM dans un seul Dockerfile. Chaque FROM démarre une nouvelle étape, et vous pouvez copier des artefacts des étapes précédentes.
La magie se produit parce que seule l'étape finale devient votre image. Les outils de construction, les compilateurs et les fichiers intermédiaires restent dans les étapes précédentes et n'arrivent jamais en production. Cela peut réduire la taille des images de 10 fois ou plus.
Conseil rapide : Nommez vos étapes avec AS builder afin de pouvoir les référencer plus tard avec COPY --from=builder. Cela rend votre Dockerfile plus lisible et maintenable.
Images Alpine : Petites mais puissantes
Alpine Linux est une distribution Linux minimale qui ne fait que 5 Mo. Comparez cela aux images basées sur Ubuntu à plus de 900 Mo. Pour la plupart des applications, Alpine fournit tout ce dont vous avez besoin.
Le compromis est qu'Alpine utilise musl libc au lieu de glibc, ce qui peut occasionnellement causer des problèmes de compatibilité avec les binaires précompilés. Pour 95 % des cas d'utilisation, Alpine fonctionne parfaitement et réduit considérablement la taille de l'image, le temps de téléchargement et la surface d'attaque.
Le fichier .dockerignore
Tout comme .gitignore, un fichier .dockerignore indique à Docker quels fichiers exclure lors de la construction d'images. Cela accélère les constructions et réduit la taille de l'image.
# Exemple de .dockerignore
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.env.local
dist
coverage
.vscode
.idea
*.log
.DS_Store
Meilleures pratiques de sécurité
La sécurité doit être intégrée dans vos Dockerfiles dès le départ :
- Ne jamais exécuter en tant que root : Utilisez
USER nodeou créez un utilisateur dédié - Épingler des versions spécifiques : Utilisez
node:22.1.0-alpineet nonnode:latest - Scanner les vulnérabilités : Utilisez
docker scan myimagepour vérifier les CVE connus - Minimiser les paquets installés : Moins de logiciels signifie moins de vulnérabilités
- Utiliser des images de base officielles : Elles sont maintenues et régulièrement mises à jour
- Ne pas stocker de secrets dans les images : Utilisez des variables d'environnement ou des outils de gestion de secrets
Besoin d'aide pour générer des Dockerfiles optimisés ? Essayez notre outil Générateur de Dockerfile.
Commandes Docker essentielles
Maîtriser ces commandes couvrira 90 % de votre utilisation quotidienne de Docker. Chaque commande inclut des exemples pratiques et des drapeaux courants.
Construction et exécution
# Construire une image à partir du Dockerfile dans le répertoire actuel
docker build -t myapp:1.0 .
# Construire avec des arguments de construction
docker build --build-arg NODE_ENV=production -t myapp:1.0 .
# Construire sans cache (forcer la reconstruction)
docker build --no-cache -t myapp:1.0 .
# Exécuter un conteneur en mode détaché
docker run -d -p 3000:3000 --name myapp myapp:1.0
# Exécuter avec des variables d'environnement
docker run -d -p 3000:3000 -e NODE_ENV=production --name myapp myapp:1.0
# Exécuter avec montage de volume
docker run -d -p 3000:3000 -v $(pwd)/data:/app/data --name myapp myapp:1.0
# Exécuter de manière interactive avec accès au shell
docker run -it --rm myapp:1.0 sh
Gestion des conteneurs
# Lister les conteneurs en cours d'exécution
docker ps
# Lister tous les conteneurs (y compris arrêtés)
docker ps -a
# Afficher les journaux du conteneur
docker logs myapp
# Suivre les journaux en temps réel
docker logs -f myapp
# Afficher les 100 dernières lignes des journaux
docker logs --tail 100 myapp
# Exécuter une commande dans un conteneur en cours d'exécution
docker exec -it myapp sh
# Exécuter une commande ponctuelle
docker exec myapp npm test
# Arrêter un conteneur gracieusement
docker stop myapp
# Tuer un conteneur immédiatement
docker kill myapp
# Supprimer un conteneur arrêté
docker rm myapp
# Arrêter et supprimer en une seule commande
docker stop myapp && docker rm myapp
# Supprimer tous les conteneurs arrêtés
docker container prune
Travailler avec les images
# Lister toutes les images
docker images
# Lister les images avec un format personnalisé
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
# Supprimer une image
docker rmi myapp:1.0
# Supprimer toutes les images inutilisées
docker image prune -a
# Étiqueter une image
docker tag myapp:1.0 myapp:latest
# Pousser vers le registre
docker push myregistry.com/myapp:1.0
# Tirer depuis le registre
docker pull myregistry.com/myapp:1.0
# Sauvegarder l'image dans un fichier tar
docker save myapp:1.0 > myapp.tar
# Charger l'image depuis un fichier tar
docker load < myapp.tar
Gestion du système
# Afficher l'utilisation du disque
docker system df
# Supprimer toutes les données inutilisées (conteneurs, réseaux, images, cache)
docker system prune -a
# Afficher les statistiques des conteneurs en temps réel
docker stats
# Inspecter les détails du conteneur (sortie JSON)
docker inspect myapp
# Afficher les processus du conteneur
docker top myapp
Conseil de pro : Ajoutez le drapeau --rm lors de l'exécution de conteneurs pour les tests. Cela supprime automatiquement le conteneur lorsqu'il s'arrête, gardant votre système propre : docker run --rm -it myapp:1.0 sh
Docker Compose pour les applications multi-conteneurs
Docker Compose est un outil pour définir et exécuter des applications multi-conteneurs. Au lieu d'exécuter plusieurs commandes docker run, vous définissez tout dans un seul fichier YAML.
C'est essentiel pour les applications modernes qui se composent généralement de plusieurs services : un serveur web, une base de données, un cache, une file d'attente de messages, et plus encore.
Exemple complet de Docker Compose
# docker-compose.yml
version: '3.8'
services:
# W