Lab 3.2 : Cache et couches¶
| Durée | 45 min |
| Niveau | Guidé |
| Prérequis | Lab 3.1 : Écrire un premier Dockerfile (dossier tp-flask et images monapp:1.0 et monapp:1.1), section 4 du cours |
| Acquis visés | AA3 |
Objectifs
- Reconnaître dans la sortie de
docker buildles étapes lues dans le cache et celles qui sont réexécutées - Mesurer l'effet d'un mauvais ordre des instructions
- Réécrire le Dockerfile pour exploiter le cache
- Observer les couches d'une image avec
docker history - Forcer une reconstruction complète avec
--no-cache
Contexte et schéma¶
Vous reprenez le projet du Lab 3.1 et vous comparez deux ordres d'instructions. Dans la version du Lab 3.1, la copie du code précède l'installation des dépendances : chaque modification du code relance l'installation.
flowchart LR
subgraph A["Ordre du Lab 3.1"]
direction TB
A1["FROM"] --> A2["WORKDIR"] --> A3["COPY . ."] --> A4["RUN pip install"] --> A5["CMD"]
end
subgraph B["Ordre optimisé"]
direction TB
B1["FROM"] --> B2["WORKDIR"] --> B3["COPY requirements.txt"] --> B4["RUN pip install"] --> B5["COPY . ."] --> B6["CMD"]
end
Selon votre option
Les commandes de mesure du temps diffèrent entre Linux (time) et PowerShell (Measure-Command). Dans les deux cas, vous pouvez vous contenter de comparer les durées affichées par Docker pour chaque étape.
Étapes¶
Étape 1 : Reprendre le projet¶
Vérifiez que le Dockerfile est celui du Lab 3.1 (COPY . . avant RUN pip install). Si le dossier ou les images ont disparu, reprenez le Lab 3.1.
Point de contrôle
- Le Dockerfile contient
COPY . .avantRUN pip install -
docker imagesaffichemonapp:1.1
Étape 2 : Reconstruire sans rien changer¶
Comme rien n'a changé, Docker réutilise toutes les couches.
Point de contrôle
- Toutes les étapes sont marquées
CACHED(ouUsing cacheselon l'affichage) - La construction est quasi instantanée
Étape 3 : Modifier le code avec l'ancien ordre¶
Dans app.py, changez le message, par exemple :
Reconstruisez et mesurez :
Notez dans le tableau d'observation (ci-dessous) les étapes CACHED et celles qui sont exécutées de nouveau.
Point de contrôle
-
FROMetWORKDIRsont lues dans le cache -
COPY . .etRUN pip installsont réexécutées - Vous avez noté la durée totale
Étape 4 : Réécrire le Dockerfile avec le bon ordre¶
Remplacez le contenu du Dockerfile par :
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
La liste des dépendances est maintenant copiée seule, avant l'installation. Construisez la nouvelle version :
Cette première construction avec le nouvel ordre réexécute l'installation, car le Dockerfile a changé.
Point de contrôle
- La construction réussit
- L'étape
RUN pip installest exécutée (elle n'est pas dans le cache)
Étape 5 : Modifier le code avec le nouvel ordre¶
Changez à nouveau le message dans app.py :
Reconstruisez et mesurez :
Point de contrôle
-
RUN pip installest maintenantCACHED - Seule la dernière copie (
COPY . .) est exécutée de nouveau - La construction est nettement plus rapide qu'à l'étape 3
Étape 6 : Modifier la liste des dépendances¶
Ajoutez une ligne de commentaire à la fin de requirements.txt :
Reconstruisez :
Même si le contenu utile n'a pas changé, le fichier n'est plus identique : Docker réinstalle donc les dépendances.
Point de contrôle
-
COPY requirements.txt .est exécutée de nouveau -
RUN pip installest exécutée de nouveau
Étape 7 : Observer les couches¶
Comparez les deux historiques : repérez la couche de l'installation de Flask et la couche de copie du code, leurs tailles et leur ordre.
Point de contrôle
- Vous avez identifié l'ordre des couches
COPYetRUNdans chacune des deux images - La couche de copie du code est bien plus petite que celle de l'installation des dépendances
Étape 8 : Forcer une reconstruction complète¶
Cette fois, aucune étape n'est lue dans le cache. Vérifiez enfin que l'application fonctionne :
Point de contrôle
- Aucune étape n'est marquée
CACHED -
curlaffiche le message de l'application
Tableau d'observation¶
Recopiez et complétez ce tableau dans votre carnet de TP.
| Étape | Modification | Étapes CACHED |
Étapes exécutées | Durée |
|---|---|---|---|---|
| 2 | Aucune | |||
| 3 | Code, ancien ordre | |||
| 5 | Code, nouvel ordre | |||
| 6 | requirements.txt |
|||
| 8 | --no-cache |
Questions de réflexion¶
Pourquoi l'étape 3 réexécute-t-elle l'installation des dépendances alors qu'elles n'ont pas changé ?
COPY . . précède RUN pip install. En modifiant app.py, le résultat de la copie change, ce qui invalide la couche de copie et toutes celles qui la suivent, dont l'installation.
Pourquoi l'étape 5 est-elle plus rapide ?
Avec le nouvel ordre, RUN pip install ne dépend que de requirements.txt, qui n'a pas changé. Docker la lit dans le cache ; seule la copie du code, qui est la dernière étape, est refaite.
Dans quelle situation faut-il utiliser --no-cache ?
Quand on veut une image reconstruite entièrement, par exemple pour récupérer des versions plus récentes de paquets installés pendant la construction, car le cache ne détecte pas qu'un paquet a été mis à jour sur Internet.
Dépannage¶
| Symptôme | Pistes |
|---|---|
Aucune étape n'est CACHED à l'étape 2 |
Le cache a pu être supprimé, ou la construction précédente n'a pas eu lieu avec ce dossier : refaites une construction, puis une seconde |
| L'étape 5 réexécute l'installation | Vérifiez que COPY requirements.txt . et RUN pip install précèdent bien COPY . . dans le Dockerfile |
docker images n'affiche pas monapp:1.1 |
Reprenez le Lab 3.1 ou reconstruisez avec docker build -t monapp:1.1 . |
The container name "/app" is already in use |
docker rm -f app |
port is already allocated |
Un autre conteneur utilise le port 5000 : docker ps, puis docker rm -f |
Nettoyage et reprise¶
docker rm -f app
docker rmi monapp:1.0 monapp:1.1 monapp:1.2 monapp:2.0 monapp:2.1 monapp:2.2 monapp:2.3
Conservez le dossier tp-flask : le mini-projet 1 peut le réutiliser.
Retour au chapitre¶
Chapitre 3 : Images et Dockerfile · Quiz : Quiz du chapitre 3