Dans cet article
- Une image Docker est un modèle immuable en couches qui contient tout le nécessaire pour exécuter une application
- Docker Hub héberge plus de 100 000 images officielles prêtes à l’emploi gratuitement
- La création d’une image personnalisée passe par un Dockerfile en moins de 10 lignes pour les cas simples
- Les images Alpine réduisent la taille finale jusqu’à 90 % par rapport à une image Ubuntu
- Le système de couches permet un cache intelligent qui accélère considérablement les builds successifs
- Les bonnes pratiques de sécurité incluent le scan régulier avec docker scout ou Trivy
Sommaire
- Qu’est-ce qu’une image Docker : définition claire
- Image et conteneur : comprendre la différence
- Structure en couches : comment fonctionne une image
- Où trouver les images Docker
- Créer une image Docker avec un Dockerfile
- Commandes essentielles pour gérer vos images
- Quelle image de base choisir selon votre projet
- Optimisation et sécurité des images Docker
- Bonnes pratiques pour vos images en production
Quand j’ai commencé à enseigner Docker à mes étudiants en BTS SIO, la notion d’images Docker était systématiquement celle qui posait le plus de questions. Pourtant, une fois le concept bien compris, tout le reste de l’écosystème Docker devient limpide. Je vous propose dans ce guide de décortiquer ensemble ce que sont réellement les images Docker, comment les trouver, les créer et les optimiser pour vos projets.
Qu’est-ce qu’une image Docker : définition claire
Une image Docker est un package léger, autonome et immuable qui contient tout ce dont une application a besoin pour s’exécuter : le code source, les dépendances, les bibliothèques système, les variables d’environnement et les fichiers de configuration. Pensez-y comme à une recette figée qui décrit exactement l’état d’un système à un instant donné.
Contrairement à une machine virtuelle qui embarque un système d’exploitation complet, une image Docker ne contient que le strict nécessaire. Elle s’appuie sur le noyau Linux de la machine hôte, ce qui explique sa légèreté remarquable. Une image Node.js basée sur Alpine pèse environ 50 Mo, contre plusieurs Go pour une VM équivalente.

En pratique, une image Docker se définit par trois caractéristiques fondamentales :
- Immuabilité : une fois construite, elle ne change jamais. Toute modification produit une nouvelle image.
- Portabilité : elle fonctionne de manière identique sur n’importe quelle machine disposant de Docker.
- Reproductibilité : à partir du même Dockerfile, vous obtenez toujours le même résultat.
Si vous débutez avec Docker, je vous recommande de consulter d’abord mon tutoriel Docker pour les débutants qui pose les bases de l’écosystème complet.
Image et conteneur : comprendre la différence
La confusion entre image et conteneur est la plus fréquente chez mes étudiants. L’analogie que j’utilise en cours fonctionne à chaque fois : l’image est la classe, le conteneur est l’instance. En programmation orientée objet, vous définissez une classe une seule fois, puis vous créez autant d’objets que nécessaire à partir de cette classe.
Le mécanisme est identique avec Docker. À partir d’une seule image nginx:alpine, vous pouvez lancer 10, 50 ou 100 conteneurs simultanés. Chaque conteneur dispose de son propre espace de stockage en écriture (une couche supplémentaire), tandis que l’image sous-jacente reste intacte et partagée entre tous les conteneurs.
| Critère | Image Docker | Conteneur Docker |
|---|---|---|
| État | Immuable (lecture seule) | Modifiable (lecture/écriture) |
| Durée de vie | Permanente jusqu’à suppression | Éphémère par conception |
| Stockage | Registry ou local | Mémoire + couche écriture |
| Création | docker build / docker pull | docker run / docker create |
| Analogie | Classe / Modèle / Recette | Instance / Objet / Plat servi |
| Partage | Partageable via registry | Propre à la machine hôte |
Cette distinction est cruciale pour comprendre les workflows de déploiement modernes. Dans un pipeline CI/CD, vous construisez l’image une seule fois, vous la poussez dans un registry, puis chaque environnement (staging, production) lance des conteneurs à partir de cette même image. C’est ce qui garantit la cohérence entre vos environnements, un sujet que je développe avec mes étudiants en développement web full stack.
Structure en couches : comment fonctionne une image
Le véritable génie technique des images Docker réside dans leur système de couches (layers). Chaque instruction de votre Dockerfile crée une nouvelle couche qui s’empile sur la précédente. Ce mécanisme s’appuie sur un système de fichiers en union (UnionFS) qui fusionne toutes les couches en un seul système de fichiers cohérent.
Prenons un exemple concret. Un Dockerfile typique pour une application Node.js génère les couches suivantes :
FROM node:20-alpine # Couche 1 : système Alpine + Node.js (~50 Mo)
WORKDIR /app # Couche 2 : création du répertoire (quelques octets)
COPY package*.json ./ # Couche 3 : fichiers de dépendances (~5 Ko)
RUN npm ci # Couche 4 : node_modules (~80 Mo)
COPY . . # Couche 5 : code source (~2 Mo)
RUN npm run build # Couche 6 : fichiers compilés (~10 Mo)
L’avantage majeur de ce système est le cache. Si vous modifiez uniquement votre code source (couche 5), Docker réutilise les couches 1 à 4 depuis le cache. Le rebuild ne prend que quelques secondes au lieu de plusieurs minutes. C’est pourquoi l’ordre des instructions dans un Dockerfile a une importance capitale : placez toujours les éléments les moins modifiés en premier.
Chaque couche est identifiée par un hash SHA256 unique. Quand deux images partagent les mêmes couches de base (ce qui arrive fréquemment avec les images officielles), Docker ne stocke ces couches qu’une seule fois sur le disque. Sur un serveur hébergeant 20 conteneurs Node.js, la couche Alpine de base n’existe qu’en un seul exemplaire.

Où trouver les images Docker
Les images Docker sont stockées et distribuées via des registries (registres). Le plus connu et le plus utilisé est Docker Hub, le registry public officiel qui héberge des millions d’images. Mais ce n’est pas la seule option.
Voici les principales sources pour trouver des images Docker :
- Docker Hub : le registry par défaut. Les images préfixées « Official Image » sont maintenues par Docker et les éditeurs logiciels. Plus de 100 000 images officielles disponibles.
- GitHub Container Registry (ghcr.io) : intégré à GitHub, idéal pour les projets open source et les pipelines GitHub Actions.
- Amazon ECR Public : le registry public d’AWS avec des images optimisées pour les services cloud.
- Google Container Registry (gcr.io) : les images officielles de Google, notamment pour Kubernetes.
- Registries privés : Harbor, GitLab Container Registry, ou votre propre registry pour les images internes.
Pour rechercher une image depuis le terminal, utilisez la commande :
docker search nginx
docker search --filter is-official=true python
Je recommande systématiquement à mes étudiants de privilégier les images officielles ou vérifiées. Une image communautaire peut contenir du code malveillant ou des vulnérabilités non corrigées. Vérifiez toujours le nombre de téléchargements, la date de dernière mise à jour et la présence d’un Dockerfile public.
Créer une image Docker avec un Dockerfile
La création d’une image Docker personnalisée passe par la rédaction d’un Dockerfile, un fichier texte qui décrit étape par étape la construction de votre image. Voici un exemple complet pour une application web Python avec Flask :
# Image de base officielle Python sur Alpine
FROM python:3.12-alpine
# Métadonnées
LABEL maintainer="[email protected]"
LABEL description="Application Flask de démonstration"
# Répertoire de travail
WORKDIR /app
# Installation des dépendances système
RUN apk add --no-cache gcc musl-dev
# Copie et installation des dépendances Python
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copie du code source
COPY . .
# Exposition du port
EXPOSE 5000
# Utilisateur non-root pour la sécurité
RUN adduser -D appuser
USER appuser
# Commande de démarrage
CMD ["python", "app.py"]
Pour construire cette image, exécutez :
docker build -t mon-app-flask:1.0 .
docker build -t mon-app-flask:latest .
Le flag -t attribue un tag à votre image (nom:version). Le point final indique que le contexte de build est le répertoire courant. Docker envoie tous les fichiers de ce répertoire au daemon pour la construction, d’où l’importance du fichier .dockerignore pour exclure les fichiers inutiles (node_modules, .git, etc.).
Les instructions Dockerfile les plus courantes sont :
- FROM : définit l’image de base (obligatoire, toujours en première ligne)
- RUN : exécute une commande pendant le build
- COPY / ADD : copie des fichiers dans l’image
- ENV : définit des variables d’environnement
- EXPOSE : documente le port utilisé par l’application
- CMD / ENTRYPOINT : définit la commande exécutée au démarrage du conteneur
Pour aller plus loin sur l’intégration de Docker dans un workflow de développement complet, consultez mon article sur le développement d’applications web sur mesure.
Commandes essentielles pour gérer vos images
Maîtriser les commandes de gestion des images Docker est indispensable au quotidien. Voici les commandes que j’utilise le plus fréquemment et que je considère comme le kit de survie minimum :
# Télécharger une image depuis un registry
docker pull nginx:alpine
docker pull python:3.12-slim
# Lister les images locales
docker images
docker image ls --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
# Inspecter une image (métadonnées, couches, configuration)
docker inspect nginx:alpine
docker history nginx:alpine
# Taguer une image pour un registry distant
docker tag mon-app:latest registry.exemple.fr/mon-app:1.0
# Pousser une image vers un registry
docker push registry.exemple.fr/mon-app:1.0
# Supprimer une image locale
docker rmi nginx:alpine
docker image prune -a # Supprime toutes les images non utilisées
# Exporter/importer une image (sans registry)
docker save mon-app:latest -o mon-app.tar
docker load -i mon-app.tar
La commande docker image prune est particulièrement utile en développement. Après plusieurs builds successifs, les images intermédiaires (appelées « dangling images ») s’accumulent et consomment de l’espace disque. Sur mes postes de développement, je lance régulièrement un nettoyage qui libère souvent plusieurs Go.
Pour visualiser l’espace consommé par Docker sur votre machine :
docker system df
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
# Images 45 12 8.2GB 5.1GB (62%)
# Containers 15 3 250MB 200MB (80%)
# Build Cache 89 0 2.1GB 2.1GB
Quelle image de base choisir selon votre projet
Le choix de l’image de base est une décision architecturale qui impacte la taille, la sécurité et la performance de vos conteneurs. Il n’existe pas de « meilleure image Docker » universelle, mais des choix adaptés à chaque contexte.
| Image de base | Taille approximative | Cas d’usage recommandé | Avantages |
|---|---|---|---|
| alpine | ~5 Mo | Production, microservices | Ultra-légère, surface d’attaque minimale |
| slim (Debian) | ~80 Mo | Applications nécessitant glibc | Bon compromis taille/compatibilité |
| ubuntu | ~75 Mo | Développement, CI/CD | Familier, large écosystème de paquets |
| debian (bookworm) | ~120 Mo | Applications complexes | Stabilité, compatibilité maximale |
| distroless (Google) | ~20 Mo | Production sécurisée | Pas de shell, surface d’attaque quasi nulle |
| scratch | 0 Mo | Binaires Go/Rust compilés | Image la plus petite possible |

Mon conseil pour les étudiants : commencez avec les variantes slim qui offrent un excellent compromis. Passez à Alpine une fois que vous maîtrisez les subtilités de musl (la bibliothèque C alternative utilisée par Alpine). Pour les applications compilées en Go ou Rust, l’image scratch produit des conteneurs incroyablement légers, parfois sous les 10 Mo.
En production, les images distroless de Google représentent l’état de l’art en matière de sécurité. Elles ne contiennent ni shell, ni gestionnaire de paquets, ni utilitaires système : uniquement votre application et ses dépendances runtime.
Pour les projets qui utilisent Docker Compose avec plusieurs services, le choix cohérent des images de base facilite la maintenance. J’aborde ce sujet dans mon guide Docker complet.
Optimisation et sécurité des images Docker
Une image Docker mal construite peut peser plusieurs Go et contenir des dizaines de vulnérabilités. L’optimisation n’est pas un luxe : c’est une nécessité opérationnelle qui impacte directement vos temps de déploiement et votre posture de sécurité.
Multi-stage builds
La technique du multi-stage build est la plus efficace pour réduire la taille de vos images. Le principe : utiliser une première image volumineuse pour la compilation, puis copier uniquement les artefacts nécessaires dans une image finale légère.
# Étape 1 : compilation
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Étape 2 : image de production
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Résultat : l’image finale ne contient que Nginx et vos fichiers statiques compilés. Les outils de build (Node.js, npm, les node_modules) restent dans l’étape intermédiaire et ne sont jamais inclus dans l’image finale. On passe typiquement de 1,2 Go à moins de 30 Mo.
Scanner les vulnérabilités
Je recommande de scanner systématiquement vos images avec docker scout (intégré à Docker Desktop) ou Trivy (open source) :
# Avec Docker Scout
docker scout cves mon-app:latest
# Avec Trivy
trivy image mon-app:latest
Intégrez ces scans dans votre pipeline CI/CD pour bloquer automatiquement les déploiements contenant des vulnérabilités critiques. C’est un principe fondamental de la sécurité informatique appliqué aux conteneurs.
Réduire la surface d’attaque
- Exécutez vos applications avec un utilisateur non-root (instruction USER)
- Utilisez un fichier
.dockerignorepour exclure secrets, fichiers .env et répertoires .git - Mettez à jour régulièrement vos images de base pour bénéficier des correctifs de sécurité
- Préférez
COPYàADDsauf si vous avez besoin de la décompression automatique
Pour approfondir les questions de sécurité dans un contexte professionnel, consultez mon guide sur l’audit de sécurité informatique.
Bonnes pratiques pour vos images en production
Après plusieurs années à déployer des images Docker en production et à former des étudiants, voici les règles d’or que j’applique systématiquement :
1. Toujours taguer explicitement vos images. N’utilisez jamais le tag latest en production. Préférez des tags sémantiques (mon-app:2.1.3) ou basés sur le commit Git (mon-app:a1b2c3d). Cela garantit la traçabilité et facilite les rollbacks.
2. Un processus par conteneur. Chaque conteneur doit exécuter un seul processus principal. Si votre application a besoin d’un serveur web et d’une base de données, utilisez deux conteneurs orchestrés avec Docker Compose.
3. Optimisez l’ordre des couches. Placez les instructions qui changent rarement en haut du Dockerfile (installation des dépendances système) et celles qui changent souvent en bas (copie du code source). Cela maximise l’utilisation du cache.
4. Combinez les commandes RUN. Chaque instruction RUN crée une couche. Combinez les commandes avec && et nettoyez les caches dans la même instruction :
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
5. Utilisez des fichiers .dockerignore exhaustifs. Excluez systématiquement : .git, node_modules, __pycache__, .env, les fichiers de logs et les artefacts de build locaux.
6. Documentez avec des LABEL. Ajoutez des métadonnées à vos images (mainteneur, version, description) pour faciliter la gestion à grande échelle.
7. Testez vos images localement. Avant de pousser une image, vérifiez qu’elle démarre correctement, que les health checks passent et que les ports sont accessibles. Les outils comme container-structure-test de Google automatisent ces vérifications.
Ces pratiques s’inscrivent dans une démarche DevOps plus large. Si vous envisagez une carrière dans ce domaine, la formation informatique à distance offre des parcours adaptés pour monter en compétence progressivement.
À retenir
- Privilégiez toujours les images officielles de Docker Hub comme base de vos projets
- Utilisez des multi-stage builds pour réduire la taille de vos images de 80 à 90 %
- Scannez vos images avec docker scout ou Trivy avant chaque déploiement en production
- Taguez explicitement vos images avec des versions sémantiques, jamais uniquement « latest »
- Exécutez vos conteneurs avec un utilisateur non-root pour limiter la surface d’attaque
Questions fréquentes
Qu’est-ce qu’une image Docker ?
Une image Docker est un package immuable et autonome qui contient tout le nécessaire pour exécuter une application : code source, dépendances, bibliothèques système et configuration. Elle fonctionne comme un modèle à partir duquel on lance des conteneurs. Construite en couches successives via un Dockerfile, elle garantit que l’application s’exécute de manière identique sur n’importe quel environnement disposant de Docker.
Où trouver les images Docker ?
Le principal registry public est Docker Hub (hub.docker.com) qui héberge plus de 100 000 images officielles maintenues par les éditeurs logiciels. D’autres options existent : GitHub Container Registry (ghcr.io), Amazon ECR Public, Google Container Registry. Pour les projets d’entreprise, des registries privés comme Harbor ou GitLab Container Registry permettent de stocker vos images internes de manière sécurisée.
Comment faire une image Docker ?
Pour créer une image Docker, rédigez un fichier nommé Dockerfile qui décrit les étapes de construction : image de base (FROM), installation des dépendances (RUN), copie du code (COPY) et commande de démarrage (CMD). Lancez ensuite la commande « docker build -t nom-image:tag . » depuis le répertoire contenant le Dockerfile. L’image est alors disponible localement et peut être poussée vers un registry avec « docker push ».
Quelle est la meilleure image Docker ?
Il n’existe pas de meilleure image universelle. Le choix dépend du contexte : Alpine (~5 Mo) pour les microservices en production, les variantes slim (~80 Mo) pour un bon compromis taille/compatibilité, distroless pour la sécurité maximale, et scratch (0 Mo) pour les binaires compilés Go ou Rust. Pour débuter, les images slim officielles de votre langage constituent le meilleur point de départ.
Comment réduire la taille d’une image Docker ?
Les techniques les plus efficaces sont : utiliser des multi-stage builds pour séparer la compilation de l’exécution, choisir une image de base légère (Alpine ou slim), combiner les instructions RUN avec && pour limiter le nombre de couches, nettoyer les caches dans la même instruction RUN, et utiliser un .dockerignore strict pour exclure les fichiers inutiles du contexte de build.
Quelle différence entre docker pull et docker build ?
La commande docker pull télécharge une image existante depuis un registry distant (Docker Hub par exemple) vers votre machine locale. La commande docker build crée une nouvelle image à partir d’un Dockerfile que vous avez rédigé. En pratique, docker build exécute souvent un docker pull implicite pour récupérer l’image de base spécifiée dans l’instruction FROM de votre Dockerfile.
Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.