Docker pour les débutants : Les conteneurs simplifiés

· 12 min de lecture

Table des matières

Qu'est-ce que Docker ?

Docker est une plateforme qui vous permet d'empaqueter des applications et leurs dépendances dans des conteneurs légers et portables. Imaginez un conteneur comme une petite boîte autonome qui contient tout ce dont votre application a besoin pour fonctionner : code, environnement d'exécution, bibliothèques et outils système. Fini les problèmes du type « ça marche sur ma machine ».

Avant Docker, déployer un logiciel signifiait installer manuellement les dépendances, configurer les serveurs et espérer qu'il n'y ait pas de conflits. Vous passiez des heures à configurer les versions de Python, les packages Node.js, les pilotes de base de données et les bibliothèques système. Ensuite, vous deviez tout refaire sur les serveurs de staging et de production, en priant pour que les configurations correspondent.

Docker élimine ce chaos en garantissant que votre application fonctionne de manière identique partout — sur votre ordinateur portable, la machine d'un coéquipier, les serveurs de staging ou de production. Le conteneur devient l'unité de déploiement, pas seulement le code de l'application.

Docker est devenu l'outil standard pour le développement logiciel moderne. Que vous construisiez des microservices, mettiez en place des pipelines CI/CD ou souhaitiez simplement un environnement de développement cohérent, Docker le rend possible avec un minimum de surcharge. Des entreprises comme Netflix, Spotify et PayPal exécutent des millions de conteneurs en production chaque jour.

Conseil rapide : Docker n'est pas seulement pour les déploiements en production. De nombreux développeurs l'utilisent pour éviter d'encombrer leur machine locale avec différentes versions de langages, bases de données et outils. Besoin de PostgreSQL pour un projet et MySQL pour un autre ? Exécutez-les tous les deux dans des conteneurs sans conflits.

Conteneurs vs machines virtuelles

Les conteneurs et les machines virtuelles offrent tous deux une isolation, mais ils fonctionnent très différemment sous le capot. Comprendre cette différence est crucial pour apprécier pourquoi les conteneurs sont devenus si populaires.

Les machines virtuelles exécutent un système d'exploitation complet avec son propre noyau au-dessus d'un hyperviseur. Chaque VM nécessite sa propre installation d'OS, consommant des gigaoctets d'espace disque et une mémoire importante. Les temps de démarrage se mesurent en minutes. Si vous exécutez trois VM, vous exécutez trois systèmes d'exploitation complets simultanément.

Les conteneurs partagent le noyau de l'OS hôte et n'empaquetent que la couche application. Ils font des mégaoctets (pas des gigaoctets), démarrent en secondes (pas en minutes), et vous pouvez en exécuter des dizaines sur une seule machine sans problème.

# Approche VM : Chaque app obtient un OS complet
App A → OS invité → Hyperviseur → OS hôte → Matériel
App B → OS invité → Hyperviseur → OS hôte → Matériel

# Approche conteneur : Les apps partagent le noyau
App A → Environnement d'exécution de conteneur → OS hôte → Matériel
App B → Environnement d'exécution de conteneur → OS hôte → Matériel

Cette architecture légère rend les conteneurs idéaux pour les microservices, où vous pourriez exécuter des centaines de petits services au lieu d'une application monolithique. L'efficacité des ressources est stupéfiante — un serveur qui exécute 10 VM pourrait confortablement exécuter 100 conteneurs.

Fonctionnalité Machines virtuelles Conteneurs
Temps de démarrage Minutes Secondes
Espace disque Gigaoctets (OS complet) Mégaoctets (couche app uniquement)
Performance Quasi-native Native (pas de surcharge d'hyperviseur)
Isolation Complète (noyau séparé) Niveau processus (noyau partagé)
Portabilité Limitée (dépendant de l'hyperviseur) Élevée (fonctionne partout où Docker fonctionne)
Utilisation des ressources Lourde Légère

Cela dit, les VM ne sont pas obsolètes. Elles offrent une isolation plus forte puisque chaque VM a son propre noyau. Pour les charges de travail critiques en matière de sécurité ou lorsque vous devez exécuter différents systèmes d'exploitation, les VM restent le meilleur choix. De nombreuses organisations utilisent les deux : des VM pour l'isolation de l'infrastructure et des conteneurs pour le déploiement d'applications.

Concepts fondamentaux de Docker

Docker a quelques concepts clés que vous devez comprendre avant de plonger dans les commandes et les Dockerfiles. Ces éléments de base forment le fondement du fonctionnement de Docker.

Images

Une image Docker est un modèle en lecture seule contenant le code de votre application, l'environnement d'exécution, les bibliothèques et les dépendances. Considérez-la comme un instantané ou un plan. Les images sont construites à partir d'instructions dans un Dockerfile et stockées dans des registres comme Docker Hub.

Les images sont composées de couches. Chaque instruction dans un Dockerfile crée une nouvelle couche. Docker met en cache ces couches, donc si vous reconstruisez une image et que seule la dernière couche a changé, Docker réutilise les couches en cache. Cela rend les builds incroyablement rapides.

Conteneurs

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, et chacun s'exécute de manière isolée. Lorsque vous arrêtez un conteneur, toutes les modifications apportées à l'intérieur sont perdues sauf si vous les enregistrez explicitement ou utilisez des volumes.

Les conteneurs sont éphémères par conception. Cette immuabilité est une fonctionnalité, pas un bug — elle garantit la cohérence et rend la mise à l'échelle triviale.

Dockerfile

Un Dockerfile est un fichier texte contenant des instructions pour construire une image Docker. Il spécifie l'image de base, copie votre code, installe les dépendances et définit comment exécuter votre application. Nous approfondirons les Dockerfiles dans une section ultérieure.

Registre Docker

Un registre est un système de stockage et de distribution pour les images Docker. Docker Hub est le registre public par défaut, hébergeant des millions d'images. Vous pouvez également exécuter des registres privés pour les applications propriétaires. Lorsque vous exécutez docker pull nginx, Docker télécharge l'image nginx depuis Docker Hub.

Volumes

Les volumes sont le mécanisme de Docker pour persister les données. Puisque les conteneurs sont éphémères, toutes les données écrites à l'intérieur d'un conteneur disparaissent lorsqu'il s'arrête. Les volumes vous permettent de stocker des données en dehors du système de fichiers du conteneur, survivant aux redémarrages et suppressions de conteneurs.

Conseil pro : Utilisez notre Générateur de commandes Docker pour créer rapidement des commandes Docker complexes sans mémoriser tous les drapeaux et options.

Commandes Docker essentielles

Parcourons les commandes Docker que vous utiliserez quotidiennement. Celles-ci couvrent l'ensemble du cycle de vie du conteneur, du téléchargement d'images au nettoyage des ressources.

Travailler avec les images

# Télécharger une image depuis Docker Hub
docker pull ubuntu:22.04

# Lister toutes les images locales
docker images

# Supprimer une image
docker rmi ubuntu:22.04

# Construire une image à partir d'un Dockerfile
docker build -t myapp:1.0 .

# Étiqueter une image pour la pousser vers un registre
docker tag myapp:1.0 username/myapp:1.0

# Pousser une image vers un registre
docker push username/myapp:1.0

Exécuter des conteneurs

# Exécuter un conteneur au premier plan
docker run ubuntu:22.04 echo "Hello Docker"

# Exécuter un conteneur en mode détaché (arrière-plan)
docker run -d nginx

# Exécuter avec un nom personnalisé
docker run -d --name my-nginx nginx

# Exécuter avec mappage de port (hôte:conteneur)
docker run -d -p 8080:80 nginx

# Exécuter avec des variables d'environnement
docker run -d -e POSTGRES_PASSWORD=secret postgres

# Exécuter avec un montage de volume
docker run -d -v /host/path:/container/path nginx

# Exécuter de manière interactive avec un shell
docker run -it ubuntu:22.04 /bin/bash

Gérer les conteneurs

# Lister les conteneurs en cours d'exécution
docker ps

# Lister tous les conteneurs (y compris arrêtés)
docker ps -a

# Arrêter un conteneur
docker stop my-nginx

# Démarrer un conteneur arrêté
docker start my-nginx

# Redémarrer un conteneur
docker restart my-nginx

# Supprimer un conteneur
docker rm my-nginx

# Supprimer un conteneur en cours d'exécution (forcer)
docker rm -f my-nginx

# Voir les journaux du conteneur
docker logs my-nginx

# Suivre les journaux en temps réel
docker logs -f my-nginx

# Exécuter une commande dans un conteneur en cours d'exécution
docker exec my-nginx ls /usr/share/nginx/html

# Ouvrir un shell dans un conteneur en cours d'exécution
docker exec -it my-nginx /bin/bash

# Voir l'utilisation des ressources du conteneur
docker stats

# Inspecter les détails du conteneur
docker inspect my-nginx

Commandes de nettoyage

# Supprimer tous les conteneurs arrêtés
docker container prune

# Supprimer les images inutilisées
docker image prune

# Supprimer les volumes inutilisés
docker volume prune

# Supprimer tout ce qui est inutilisé (conteneurs, images, réseaux, volumes)
docker system prune -a

Les drapeaux -it méritent une mention spéciale. -i garde STDIN ouvert (interactif), et -t alloue un pseudo-TTY (terminal). Ensemble, ils vous permettent d'interagir avec le conteneur comme une session shell normale.

Conseil rapide : Utilisez docker ps -q pour obtenir uniquement les ID de conteneurs, ce qui est utile pour les scripts. Par exemple, docker stop $(docker ps -q) arrête tous les conteneurs en cours d'exécution.

Écrire des Dockerfiles

Un Dockerfile est là où la magie opère. C'est une recette pour construire votre image Docker, spécifiant exactement ce qui entre dans votre conteneur. Décomposons les instructions les plus importantes et les meilleures pratiques.

Structure de base d'un Dockerfile

# Partir d'une image de base
FROM node:18-alpine

# Définir le répertoire de travail
WORKDIR /app

# Copier les fichiers de package
COPY package*.json ./

# Installer les dépendances
RUN npm install

# Copier le code de l'application
COPY . .

# Exposer le port sur lequel votre app s'exécute
EXPOSE 3000

# Définir la commande pour exécuter votre app
CMD ["node", "server.js"]

Instructions clés du Dockerfile

FROM spécifie l'image de base. Utilisez toujours des balises de version spécifiques (comme node:18-alpine) au lieu de latest pour garantir des builds reproductibles. Les variantes Alpine sont plus petites et plus sécurisées.

WORKDIR définit le répertoire de travail pour les instructions suivantes. Il crée le répertoire s'il n'existe pas. C'est plus propre que d'utiliser RUN cd /app.

COPY copie les fichiers de votre machine hôte dans l'image. La syntaxe est COPY source destination. Utilisez COPY . . pour tout copier, mais faites attention à ce que vous incluez (utilisez .dockerignore).

RUN exécute des commandes pendant le processus de build. Chaque instruction RUN crée une nouvelle couche. Enchaînez les commandes avec && pour réduire les couches :

# Mauvais : Crée 3 couches
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get clean

# Bon : Crée 1 couche
RUN apt-get update && \
    apt-get install -y curl && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

EXPOSE documente sur quel port votre application écoute. Il ne publie pas réellement le port — cela se fait avec docker run -p.

CMD spécifie la commande par défaut à exécuter lorsque le conteneur démarre. Utilisez le format de tableau JSON (["executable", "param1"]) pour éviter les problèmes de traitement du shell.

ENTRYPOINT est similaire à CMD mais plus difficile à remplacer. Utilisez-le lorsque vous voulez que votre conteneur se comporte comme un exécutable. Vous pouvez combiner ENTRYPOINT et CMD pour des valeurs par défaut flexibles.

Builds multi-étapes

Les builds multi-étapes vous permettent d'utiliser plusieurs instructions FROM dans un seul Dockerfile. C'est incroyablement puissant pour créer de petites images de production tout en gardant les outils de build séparés.

# Étape de build
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Étape de production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
EXPOSE 3000
CMD ["node", "dist/server.js"]

L'image de production ne contient que le code compilé et les dépendances d'exécution, pas les outils de build. Cela peut réduire la taille de l'image de 70 % ou plus.

Fichier .dockerignore

Créez un fichier .dockerignore pour exclure des fichiers du contexte de build. Cela accélère les builds et réduit la taille de l'image.

node_modules
npm-debug.log
.git
.env
*.md
.DS_Store
coverage
.vscode