Docker pour développeurs : images, conteneurs et Compose
Vous avez entendu parler de Docker et des conteneurs, mais lorsque vous essayez de l'utiliser, vous êtes submergé par des termes comme images, conteneurs, volumes et Compose. Ou peut-être utilisez-vous déjà Docker, mais vos images sont énormes, les builds sont lents et la gestion de plusieurs services ressemble à une corvée. Ce guide va droit au but. Nous couvrirons l'essentiel de Docker pour les développeurs, en nous concentrant sur ce que vous devez réellement savoir pour créer, exécuter et gérer efficacement des applications conteneurisées.
Pourquoi Docker ? Le problème qu'il résout
Avant Docker, déployer une application signifiait reproduire l'environnement exact : versions spécifiques du système d'exploitation, bibliothèques et configurations. « Ça marche sur ma machine » est devenu un cliché parce que c'était vrai. Docker résout ce problème en empaquetant votre application avec ses dépendances dans une unité portable unique appelée conteneur. Les conteneurs sont légers, isolés et s'exécutent de manière cohérente partout où Docker est installé.
Images vs conteneurs : la distinction fondamentale
Une image est un modèle en lecture seule qui contient le code de votre application, son runtime, ses bibliothèques et ses paramètres. Un conteneur est une instance en cours d'exécution d'une image. Considérez une image comme une classe et un conteneur comme un objet. Vous pouvez exécuter plusieurs conteneurs à partir de la même image, chacun isolé des autres.
Comment les images sont construites
Les images sont construites à partir d'un Dockerfile, un fichier texte contenant des instructions. Voici un exemple minimal pour une application Node.js :
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Chaque instruction crée une couche. Les couches sont mises en cache, donc si vous ne modifiez que votre code source, Docker réutilise les couches en cache pour les dépendances, ce qui accélère les reconstructions.
Construire et exécuter
Construisez l'image et exécutez un conteneur :
docker build -t my-app .
docker run -p 3000:3000 my-app
L'option -p mappe le port 3000 de votre hôte vers le port 3000 du conteneur.
Bonnes pratiques pour des images Docker efficaces
Les images volumineuses ralentissent les builds, les pushs et les déploiements. Suivez ces pratiques pour garder vos images légères :
- Utilisez des images de base officielles slim ou alpine lorsque c'est possible. Par exemple,
node:18-alpineest bien plus petite quenode:18. - Tirez parti des builds multi-étapes pour séparer les dépendances de build du runtime. Cela permet de garder l'image finale minimale.
- Combinez les commandes RUN pour réduire le nombre de couches et nettoyer les caches des gestionnaires de paquets dans la même couche.
- Utilisez un fichier .dockerignore pour exclure les fichiers inutiles (par exemple, node_modules, .git) du contexte de build.
Voici un Dockerfile multi-étapes pour une application Go :
# Build stage
FROM golang:1.21-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/main .
# Final stage
FROM alpine:latest
COPY --from=builder /app/main /main
CMD ["/main"]
L'image finale ne contient que le binaire compilé et Alpine, pas la chaîne d'outils Go.
Gérer les données avec les volumes
Les conteneurs sont éphémères ; lorsqu'ils sont supprimés, leurs données sont perdues. Les volumes persistent les données en dehors du cycle de vie du conteneur. Utilisez-les pour les bases de données, les uploads ou tout état qui doit survivre aux redémarrages.
docker run -v my-data:/var/lib/postgresql/data postgres
Cela crée un volume nommé my-data que Docker gère. Pour le développement, vous pouvez également monter votre code source dans le conteneur pour un rechargement à chaud :
docker run -v $(pwd):/app -p 3000:3000 my-app
Docker Compose : orchestrer plusieurs conteneurs
Les applications réelles ont souvent besoin de plusieurs services : un serveur web, une base de données, un cache. Démarrer chacun avec docker run est fastidieux et source d'erreurs. Docker Compose vous permet de définir et d'exécuter des applications multi-conteneurs avec un seul fichier YAML.
Un docker-compose.yml pratique
Voici un fichier Compose 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-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
cache:
image: redis:7-alpine
volumes:
postgres_data:
Exécutez docker compose up pour démarrer tous les services. Compose crée un réseau par défaut afin que les conteneurs puissent se joindre par nom de service (par exemple, db, cache).
Commandes Compose courantes
docker compose up -d– démarrer en mode détaché (arrière-plan).docker compose logs -f web– suivre les logs d'un service.docker compose exec web sh– ouvrir un shell dans un conteneur en cours d'exécution.docker compose down– arrêter et supprimer les conteneurs, réseaux et volumes (sauf si les volumes sont externes).
Quand utiliser Docker Compose vs Kubernetes
Docker Compose est idéal pour le développement local, les tests et les petits déploiements. Kubernetes excelle dans l'orchestration de conteneurs sur des clusters pour la production à grande échelle. Pour de nombreux développeurs, Compose suffit au travail quotidien, et vous pouvez passer à Kubernetes lorsque vous avez besoin d'auto-scaling, d'auto-réparation et de réseaux avancés.
| Fonctionnalité | Docker Compose | Kubernetes |
|---|---|---|
| Cas d'usage | Dév local, petits déploiements | Clusters de production |
| Complexité | Faible | Élevée |
| Scalabilité | Manuelle | Automatique |
| Courbe d'apprentissage | Douce | Raide |
FAQ
Quelle est la différence entre une image et un conteneur ?
Une image est un modèle en lecture seule contenant votre application et ses dépendances. Un conteneur est une instance en cours d'exécution d'une image. Vous pouvez exécuter plusieurs conteneurs à partir d'une seule image.
Comment réduire la taille d'une image Docker ?
Utilisez des images de base plus petites (comme Alpine), des builds multi-étapes, combinez les commandes RUN et utilisez un fichier .dockerignore pour exclure les fichiers inutiles.
Puis-je utiliser Docker Compose en production ?
Oui, pour des déploiements à petite échelle. Pour des environnements plus vastes et dynamiques, Kubernetes ou Docker Swarm est plus adapté.
Prêt à optimiser votre flux de travail Docker ? Découvrez notre Analyseur de logs Nginx pour déboguer et surveiller vos serveurs web conteneurisés.