Docker pour développeurs : images, conteneurs et Compose
Vous avez développé une application web qui fonctionne parfaitement sur votre machine, mais lorsque vous la déployez sur un serveur ou la partagez avec un collègue, elle plante. Des dépendances sont manquantes, les versions entrent en conflit ou les variables d'environnement sont incorrectes. C'est le problème classique du « ça marche sur ma machine ». Docker résout ce problème en empaquetant votre application et ses dépendances dans une unité standardisée appelée conteneur. Dans ce guide, vous apprendrez les concepts fondamentaux de Docker—images, conteneurs et Compose—et comment les utiliser pour rationaliser votre flux de travail de développement.
Qu'est-ce que Docker ?
Docker est une plateforme pour construire, exécuter et livrer des applications dans des conteneurs. Un conteneur est un paquet léger, autonome et exécutable qui inclut tout ce qui est nécessaire pour exécuter un logiciel : code, runtime, outils système, bibliothèques et paramètres. Les conteneurs isolent les applications les unes des autres et de l'infrastructure sous-jacente, garantissant ainsi la cohérence entre les environnements.
Images vs conteneurs
Une image est un modèle en lecture seule avec des instructions pour créer un conteneur. C'est comme un instantané de votre application et de son environnement. Un conteneur est une instance exécutable d'une image. Vous pouvez créer, démarrer, arrêter, déplacer ou supprimer des conteneurs à l'aide de l'API ou de la CLI Docker.
Considérez une image comme une classe et un conteneur comme un objet (instance) de cette classe. Vous pouvez exécuter plusieurs conteneurs à partir de la même image, chacun isolé des autres.
Construire une image avec un Dockerfile
Un Dockerfile est un fichier texte contenant des instructions pour construire une image. Voici un exemple simple pour une application Node.js :
# Use an official Node.js runtime as a parent image
FROM node:18-alpine
# Set the working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Expose the port the app runs on
EXPOSE 3000
# Define the command to run the app
CMD ["node", "server.js"]
Pour construire l'image, exécutez :
docker build -t my-node-app .
L'option -t attribue un nom à l'image (my-node-app). Le . à la fin spécifie le contexte de construction (répertoire courant).
Exécuter des conteneurs
Une fois que vous avez une image, vous pouvez exécuter un conteneur :
docker run -p 3000:3000 -d my-node-app
Cela mappe le port 3000 de votre hôte au port 3000 du conteneur et l'exécute en mode détaché (-d).
Commandes courantes :
docker ps– lister les conteneurs en cours d'exécutiondocker ps -a– lister tous les conteneurs (y compris ceux arrêtés)docker stop <container_id>– arrêter un conteneurdocker rm <container_id>– supprimer un conteneurdocker images– lister les imagesdocker rmi <image_id>– supprimer une image
Gérer les données avec des volumes
Les conteneurs sont éphémères ; lorsqu'ils sont supprimés, leurs données sont perdues. Pour persister les données, utilisez des volumes. Un volume est un répertoire en dehors du système de fichiers du conteneur, géré par Docker.
docker run -v my_volume:/app/data my-node-app
Vous pouvez également monter un répertoire hôte (bind mount) pour le développement :
docker run -v $(pwd):/app my-node-app
Docker Compose : applications multi-conteneurs
Les applications réelles nécessitent souvent plusieurs services : un serveur web, une base de données, un cache, etc. Docker Compose vous permet de définir et d'exécuter des applications Docker multi-conteneurs à l'aide d'un fichier YAML. Voici un exemple de docker-compose.yml pour une application Node.js avec une base de données PostgreSQL :
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:password@db:5432/mydb
depends_on:
- db
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Exécutez l'ensemble de la stack avec :
docker compose up -d
Cela construit le service web, récupère l'image Postgres, crée un réseau et démarre les deux conteneurs. Le depends_on garantit que la base de données démarre avant le service web.
Pour arrêter et supprimer les conteneurs, les réseaux et les volumes :
docker compose down -v
Bonnes pratiques pour Docker en développement
- Utilisez .dockerignore pour exclure des fichiers comme
node_moduleset.gitdu contexte de construction. - Tirez parti des builds multi-étapes pour garder les images petites. Par exemple, construisez votre application dans une étape et copiez uniquement les artefacts de production dans une image d'exécution plus petite.
- Épinglez les versions dans votre Dockerfile (par exemple,
node:18-alpineau lieu denode:latest) pour la reproductibilité. - Utilisez des volumes pour les données persistantes et des bind mounts pour le rechargement du code en direct pendant le développement.
- Gardez les conteneurs sans état ; stockez l'état dans des volumes ou des services externes.
Comparaison : Docker vs machines virtuelles
| Aspect | Conteneurs Docker | Machines virtuelles |
|---|---|---|
| Temps de démarrage | Secondes | Minutes |
| Utilisation des ressources | Léger (partage le noyau de l'OS) | Lourd (OS complet par VM) |
| Isolation | Au niveau du processus | Au niveau matériel |
| Portabilité | Élevée (fonctionne partout où Docker fonctionne) | Limitée par la compatibilité de l'hyperviseur |
FAQ
Quelle est la différence entre une image et un conteneur ?
Une image est un modèle en lecture seule qui définit l'application et son environnement. Un conteneur est une instance en cours d'exécution d'une image. Vous pouvez créer plusieurs conteneurs à partir de la même image.
Quand dois-je utiliser Docker Compose ?
Utilisez Docker Compose lorsque votre application est composée de plusieurs services (par exemple, serveur web, base de données, cache) qui doivent fonctionner ensemble. Cela simplifie l'orchestration pour le développement et les tests.
Comment persister des données dans Docker ?
Utilisez des volumes pour persister les données en dehors du système de fichiers du conteneur. Les volumes sont gérés par Docker et peuvent être partagés entre les conteneurs. Les bind mounts peuvent également être utilisés pour monter des répertoires hôtes.
Prêt à conteneuriser votre prochain projet ? Commencez par écrire un Dockerfile pour une application simple, puis ajoutez progressivement des services avec Docker Compose. Pour plus d'outils de développement, consultez notre JSON Formatter pour valider et embellir vos fichiers de configuration.