# Image Une **image Docker** est un modèle immuable qui contient : - un **système de fichiers figé** (application, bibliothèques, configuration, etc.) - des **métadonnées** (variables d’environnement, commande par défaut à exécuter, ports exposés, etc.) Elle sert de **base** pour créer des conteneurs. Contrairement à une machine virtuelle, une image n’est pas un “snapshot complet” : elle ne contient pas de noyau ni d’état d’exécution (RAM, processus, etc.). Les images sont stockées dans une **registry** (ex. [Docker Hub](https://hub.docker.com), GitHub Container Registry, GitLab, AWS ECR, Azure ACR…). > ⚠️ Attention : une *registry* est un service de stockage, tandis qu’un *repository* est un espace dans cette registry qui regroupe les différentes versions (tags) d’une même image. > Exemple : `nginx:1.25`, `nginx:latest`. --- ## Création d’une image Le moyen standard de créer une image passe par un fichier `Dockerfile`, qui décrit **étape par étape** les instructions nécessaires pour construire l’image à partir d'une image de base. ```dockerfile FROM ubuntu:24.04 RUN apt-get update && apt-get install -y nginx WORKDIR /var/www/html COPY index.html . CMD ["nginx", "-g", "daemon off;"] ``` - `FROM` : définit l’image de base - `RUN` : exécute des commandes dans une nouvelle couche - `WORKDIR` : définit le répertoire de travail par défaut - `COPY` : ajoute un fichier depuis l’hôte vers l’image - `CMD` : définit la commande exécutée par défaut dans le conteneur Construction de l’image : ```bash docker build -t monimage:1.0 . ``` Une fois l’image construite, elle peut servir à lancer autant de conteneurs que nécessaire : ```bash docker run -d -p 8080:80 monimage:1.0 ``` --- ## Immutabilité et versioning Une image est **immuable** : son contenu ne peut pas être modifié directement. Pour l’adapter, il faut **reconstruire** une nouvelle version (souvent avec un nouveau `:tag`). Exemple de gestion de tags : ```bash monimage:1.0 monimage:1.1 monimage:latest # tag par défaut si aucun n’est précisé ``` > Il existe une commande `docker commit` pour créer une image à partir d’un conteneur existant, mais cette méthode est déconseillée car elle casse la logique déclarative et reproductible du `Dockerfile`. --- ## Couches (layers) Chaque instruction dans le Dockerfile crée une **couche** (layer). Ces couches sont : - **en lecture seule** (read-only) une fois construites, - empilées les unes sur les autres, - réutilisées grâce au **cache Docker**. Lorsqu’on reconstruit une image, Docker réutilise les couches déjà valides, jusqu’à la première modification. Donc, plus une instruction change souvent, plus elle doit être placée **en bas du Dockerfile** pour maximiser la réutilisation. **Exemple :** - si on modifie seulement `index.html`, seules les couches `COPY` et `CMD` sont reconstruites, pas l’installation d’Ubuntu ni de nginx. Cela permet de : 1. Réduire le temps de build 2. Éviter de re-télécharger ou recompiler inutilement Lorsqu’un conteneur est lancé, Docker ajoute une **couche en lecture/écriture** au-dessus de l’image. Ainsi, l’image reste figée et commune à tous les conteneurs. --- ![Image](images/docker_image.png) --- ## Bonnes pratiques - **Un service = un conteneur** : ne pas mélanger plusieurs applications (ex. nginx + mysql) dans une même image. - **Utiliser des images officielles** quand elles existent (elles sont maintenues et mises à jour). - **Privilégier les images légères** (`alpine`, `slim`) pour réduire le temps de téléchargement et l’empreinte disque. - **Éviter `latest`** en production : toujours versionner explicitement (`:1.25`, `:24.04`). - **Placer les instructions fréquemment modifiées en bas** du Dockerfile pour tirer parti du cache. - **Limiter la taille des images** en nettoyant après installation (`apt-get clean`, suppression des caches). - **Définir un `WORKDIR`** clair et utiliser `COPY` au lieu de `ADD` sauf besoin spécifique. - **Spécifier `CMD` ou `ENTRYPOINT`** pour indiquer comment lancer l’application.