
Construire l'image (`docker build`)
Apprenez à utiliser la commande essentielle `docker build` pour transformer votre Dockerfile en une image Docker fonctionnelle. Découvrez le contexte, le tagging et le cache.
Introduction : de la recette à l'image concrète
Vous avez soigneusement rédigé votre Dockerfile, définissant les étapes pour créer l'environnement parfait pour votre application. Mais ce fichier texte n'est encore qu'une recette. Pour obtenir une véritable image Docker que vous pourrez exécuter sous forme de conteneur, vous devez utiliser la commande `docker build`. C'est elle qui interprète votre Dockerfile et exécute les instructions pour assembler l'image, couche par couche.
La commande `docker build` est le pont entre votre définition textuelle (le Dockerfile) et l'artefact binaire et portable (l'image Docker). Comprendre son fonctionnement, ses options principales et les mécanismes sous-jacents comme le contexte de build et le système de cache est fondamental pour travailler efficacement avec Docker et créer des images optimisées.
Ce chapitre vous guide à travers l'utilisation de `docker build`. Nous verrons comment lancer un build, comment spécifier le contexte, l'importance cruciale du tagging de vos images, et comment le système de cache de Docker peut accélérer considérablement vos builds successifs. Préparez-vous à donner vie à vos Dockerfiles !
La commande `docker build` : syntaxe et contexte de build
La forme la plus courante de la commande `docker build` est la suivante :
docker build [OPTIONS] PATH | URL | -Décortiquons les éléments essentiels :
- `[OPTIONS]` : Divers paramètres pour contrôler le processus de build. L'option la plus importante est `-t` (ou `--tag`) pour nommer et étiqueter votre image, que nous verrons juste après. Une autre option utile est `-f` (ou `--file`) pour spécifier un nom ou un chemin différent pour votre Dockerfile si celui-ci ne s'appelle pas `Dockerfile` ou n'est pas à la racine du contexte.
- `PATH | URL | -` : C'est l'emplacement du contexte de build. Le plus souvent, il s'agit d'un chemin vers un répertoire sur votre système de fichiers local, typiquement `.` pour indiquer le répertoire courant. Le contexte de build est l'ensemble des fichiers et répertoires situés à cet emplacement. Attention : Docker envoie l'intégralité de ce contexte (récursivement) au démon Docker avant de commencer le build. Un contexte volumineux peut donc ralentir considérablement le démarrage du build.
Le concept de contexte de build est crucial. Si votre Dockerfile contient une instruction `COPY ./mon_app /app`, Docker cherchera le répertoire `mon_app` à l'intérieur du contexte que vous avez spécifié (par exemple, le répertoire courant si vous utilisez `.`).
Pour éviter d'envoyer des fichiers inutiles ou sensibles (comme le répertoire `.git`, `node_modules`, des logs, des secrets, etc.) au démon Docker et de les inclure potentiellement dans votre image, utilisez un fichier `.dockerignore` à la racine de votre contexte de build. Sa syntaxe est similaire à celle d'un fichier `.gitignore`. Par exemple :
.git
.vscode
node_modules
*.log
Dockerfile
.dockerignore
README.mdUn build typique lancé depuis le répertoire contenant le Dockerfile et les sources ressemblera donc souvent à :
# Utilise le Dockerfile dans le répertoire courant (.) comme recette
# et le contenu du répertoire courant comme contexte
docker build .Tagger vos images : l'option `-t` ou `--tag`
Construire une image est une chose, mais pouvoir s'y référer facilement en est une autre. Par défaut, si vous ne spécifiez rien, l'image construite aura un identifiant unique (un long hash) mais pas de nom lisible. Pour pouvoir utiliser votre image avec `docker run`, la partager sur un registre (comme Docker Hub) ou simplement l'identifier, vous devez lui attribuer un tag.
C'est le rôle de l'option `-t` (ou `--tag`). Elle permet d'associer un nom et une étiquette (version) à votre image.
Syntaxe : `-t nom_repository:tag_version`nom_repository: Généralement le nom de votre application ou service (ex: `mon_app_web`, `backend_api`). Si vous prévoyez de pousser l'image sur Docker Hub, vous devrez préfixer ce nom par votre nom d'utilisateur Docker Hub (ex: `monutilisateur/mon_app_web`).tag_version: Une étiquette pour identifier la version ou la variante de l'image (ex: `latest`, `1.0`, `v2.1-alpine`). Il est fortement recommandé d'utiliser des tags spécifiques plutôt que de se fier uniquement à `latest`.
Vous pouvez appliquer plusieurs tags à la même image en répétant l'option `-t`.
Exemples :# Construit l'image et la tague comme "mon_api:latest"
docker build -t mon_api:latest .
# Construit l'image et lui donne deux tags : "mon_site:1.0" et "mon_site:latest"
docker build -t mon_site:1.0 -t mon_site:latest .
# Construit une image destinée à être poussée sur Docker Hub
docker build -t votre_username/super_app:v1.2 .Le tagging est essentiel pour la gestion des versions et le déploiement. Une convention de nommage claire vous facilitera grandement la vie.
Le processus de build et le miracle du cache
Lorsque vous lancez `docker build`, Docker lit votre Dockerfile et exécute chaque instruction séquentiellement.
Pour chaque instruction (sauf quelques exceptions), Docker effectue les actions suivantes :
- Il exécute l'instruction (ex: lance une commande pour `RUN`, copie des fichiers pour `COPY`).
- Si l'instruction modifie le système de fichiers, il crée une nouvelle couche d'image contenant uniquement ces modifications.
- Il génère un identifiant pour cette nouvelle couche.
La magie opère avec le cache de build. Avant d'exécuter une instruction, Docker vérifie s'il possède déjà une couche en cache correspondant exactement à cette instruction et à toutes les couches précédentes.
- Si l'instruction (par exemple, `RUN apt-get install -y vim`) n'a pas changé et que l'image parente sur laquelle elle s'applique est identique à celle d'un build précédent, Docker réutilise la couche existante depuis son cache au lieu de ré-exécuter l'instruction. Cela est indiqué par `---> Using cache` dans la sortie du build.
- Si une instruction `COPY` est rencontrée, Docker vérifie si le contenu des fichiers copiés a changé. Si ce n'est pas le cas, il utilise le cache.
- Dès qu'une instruction ne peut pas utiliser le cache (parce que l'instruction elle-même a changé, ou les fichiers qu'elle utilise ont changé, ou une couche précédente a changé), Docker exécute l'instruction et invalide le cache pour toutes les instructions suivantes dans le Dockerfile. Celles-ci devront être ré-exécutées.
Ce mécanisme de cache rend les builds successifs beaucoup plus rapides, surtout si seules les dernières étapes (souvent la copie du code source) ont changé. Pour tirer le meilleur parti du cache, structurez votre Dockerfile en plaçant les instructions les moins susceptibles de changer (comme `FROM`, l'installation de dépendances système ou de librairies via `RUN`) avant celles qui changent fréquemment (comme `COPY . .` pour votre code source).
Exemple d'optimisation de cache :
FROM python:3.9-slim
WORKDIR /app
# Copier D'ABORD le fichier de dépendances
COPY requirements.txt .
# Installer les dépendances ENSUITE (sera en cache si requirements.txt ne change pas)
RUN pip install -r requirements.txt
# Copier le reste du code (change plus souvent)
COPY . .
CMD ["python", "main.py"]Suivi du build et gestion des erreurs
Pendant le build, Docker affiche chaque étape (`Step 1/N : FROM ...`, `Step 2/N : WORKDIR ...`, etc.) et le résultat. Vous verrez soit `---> Using cache`, soit l'identifiant d'un conteneur intermédiaire utilisé pour exécuter l'instruction (`---> Running in abcdef123456`), puis le nouvel identifiant de couche (`---> fedcba987654`).
Si une instruction échoue (par exemple, une commande dans `RUN` renvoie une erreur, ou un fichier spécifié dans `COPY` n'est pas trouvé dans le contexte), le processus de build s'arrête immédiatement. Docker affichera généralement la sortie de la commande échouée, ce qui est essentiel pour le débogage. Lisez attentivement les messages d'erreur pour comprendre ce qui n'a pas fonctionné (faute de frappe, paquet manquant, problème de permissions, etc.).
Une fois le build terminé avec succès, vous verrez un message comme :
Successfully built fedcba987654
Successfully tagged mon_app:latestVotre image est alors prête ! Vous pouvez la lister avec `docker images` et l'utiliser pour lancer des conteneurs avec `docker run mon_app:latest`.