Docker pour développeurs : images, conteneurs et Compose
Vous avez développé une application qui fonctionne sur votre machine, mais au moment du déploiement, rien ne va plus. Des dépendances manquent, les versions diffèrent et la configuration est un désastre. Docker résout ce problème en empaquetant votre application et son environnement dans une unité portable unique. Cet article explique les images Docker, les conteneurs et Docker Compose avec des exemples pratiques pour rationaliser votre flux de travail de développement.
Qu'est-ce qu'une image Docker ?
Une image Docker est un modèle en lecture seule qui contient le code de votre application, le runtime, les bibliothèques, les variables d'environnement et les fichiers de configuration. Considérez-la comme un instantané de l'environnement de votre application. Les images sont construites à partir d'un Dockerfile, un fichier texte contenant des instructions.
Voici un Dockerfile simple pour une application Node.js :
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Chaque instruction crée une couche. Les couches sont mises en cache, donc une reconstruction après une modification du code ne réexécute que les étapes à partir de la couche modifiée. Cela rend les builds rapides.
Qu'est-ce qu'un conteneur Docker ?
Un conteneur est une instance en cours d'exécution d'une image. C'est un processus isolé avec son propre système de fichiers, réseau et espace de processus, mais il partage le noyau du système d'exploitation hôte. Cela rend les conteneurs légers et rapides à démarrer par rapport aux machines virtuelles.
Pour exécuter un conteneur à partir d'une image :
docker run -d -p 3000:3000 --name myapp my-node-app
Cela démarre un conteneur en mode détaché (-d), mappe le port 3000 de l'hôte vers le port 3000 du conteneur (-p 3000:3000) et le nomme myapp.
Les conteneurs sont éphémères par défaut. Toutes les données écrites à l'intérieur sont perdues à l'arrêt du conteneur. Pour persister les données, utilisez des volumes :
docker run -v /host/data:/app/data my-node-app
Pourquoi utiliser Docker Compose ?
Les applications réelles nécessitent souvent plusieurs services : un serveur web, une base de données, un cache, etc. Les exécuter individuellement avec docker run et les lier manuellement est fastidieux. Docker Compose vous permet de définir et d'exécuter des applications multi-conteneurs avec un seul fichier YAML.
Voici un docker-compose.yml pour une application Node.js avec PostgreSQL et Redis :
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
- REDIS_URL=redis://cache:6379
depends_on:
- db
- cache
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
cache:
image: redis:7
volumes:
pgdata:
Exécutez le tout avec :
docker compose up -d
Compose crée un réseau pour que les services puissent se joindre par leur nom (par exemple db, cache). Il gère également la création des volumes et l'ordre des dépendances.
Commandes Docker essentielles pour les développeurs
docker build -t myapp .– Construire une image à partir d'un Dockerfile dans le répertoire courant.docker images– Lister les images locales.docker ps– Lister les conteneurs en cours d'exécution (ajoutez-apour tous).docker exec -it myapp sh– Ouvrir un shell dans un conteneur en cours d'exécution.docker logs myapp– Consulter les logs d'un conteneur.docker compose down– Arrêter et supprimer les conteneurs, réseaux et volumes définis dans Compose.
Bonnes pratiques Docker en développement
- Utilisez .dockerignore pour exclure node_modules, .git et autres fichiers inutiles du contexte de build.
- Tirez parti des builds multi-étapes pour garder les images de production légères. Par exemple, construisez votre application dans une étape et copiez uniquement les artefacts vers une image d'exécution minimale.
- Épinglez les versions dans votre Dockerfile (par exemple
node:18-alpineau lieu denode:latest) pour des builds reproductibles. - Utilisez des volumes pour le code pendant le développement pour le rechargement à chaud :
volumes: - .:/appdans Compose. - Ne tournez pas en root en production. Créez un utilisateur non-root dans votre Dockerfile.
Pièges courants et comment les éviter
Piège 1 : Images volumineuses. Utiliser une image de base avec un OS complet comme ubuntu peut donner des images de plus de 1 Go. Utilisez les variantes slim ou alpine.
Piège 2 : Builds lents. Ordonnez les instructions du Dockerfile du moins au plus fréquemment modifié. Copiez les fichiers de paquets et installez les dépendances avant de copier le code source.
Piège 3 : Perte de données. Utilisez toujours des volumes pour les bases de données. Sans eux, les données disparaissent à la suppression du conteneur.
Piège 4 : Confusion réseau. Dans Compose, les services communiquent sur un réseau par défaut en utilisant les noms de service comme noms d'hôte. N'utilisez pas localhost pour joindre un autre service.
FAQ
Quelle est la différence entre une image et un conteneur ?
Une image est un modèle en lecture seule ; un conteneur est une instance en cours d'exécution de cette image. Vous pouvez exécuter plusieurs conteneurs à partir de la même image.
Puis-je utiliser Docker Compose en production ?
Compose est principalement destiné au développement et aux tests. Pour la production, envisagez des orchestrateurs comme Kubernetes ou Docker Swarm, bien que Compose puisse convenir pour des déploiements simples.
Comment mettre à jour un conteneur avec du nouveau code ?
Reconstruisez l'image avec docker build puis recréez le conteneur : docker compose up -d --build.
Prêt à rationaliser votre flux de travail de développement ? Essayez notre Analyseur de logs Nginx pour déboguer rapidement les logs de votre serveur web conteneurisé.