Épisode 04 / 9Les gestes essentiels30 min
Créer une image avec un Dockerfile
Jusqu’ici, vous utilisiez les images des autres. Cette fois, vous écrivez la recette, vous construisez votre propre image, puis vous en publiez une deuxième version.
Tapez les commandes dans PowerShell, avec Docker Desktop démarré : « Engine running » en bas à gauche.
Ajoutez sudo devant chaque commande docker, sauf si vous avez choisi le groupe docker à l’épisode 2.
Dans cet épisode
- Écrire un Dockerfile et comprendre chacune de ses lignes
- Construire une image, la lancer, puis en créer une nouvelle version
- Comprendre les couches et le cache, pour des constructions rapides
Jusqu’ici, vous avez utilisé une image préparée par d’autres. Cette fois, on garde Nginx comme base, mais on remplace sa page d’accueil par la vôtre. Le résultat est une image à vous, que n’importe quel ordinateur équipé de Docker pourra reconstruire à l’identique.
Étape 1 : préparer le dossier
Créez un dossier de travail, placez-vous dedans, et créez tout de suite les deux fichiers, vides, avec leur nom exact :
mkdir ~\docker-lab\mon-image
cd ~\docker-lab\mon-image
New-Item index.html, Dockerfile
Pour les remplir, ouvrez chacun dans le Bloc-notes (notepad index.html, puis
notepad Dockerfile), collez le contenu de l’étape suivante et enregistrez avec
Ctrl + S. Créer les fichiers d’abord évite le piège classique : un fichier
enregistré sous Dockerfile.txt, que Docker ne trouve pas.
Créez un dossier de travail et placez-vous dedans :
mkdir -p ~/docker-lab/mon-image
cd ~/docker-lab/mon-image
Pour créer les deux fichiers de l’étape suivante, utilisez l’éditeur nano :
nano index.html, collez le contenu (Ctrl + Maj + V), enregistrez avec Ctrl + O
puis Entrée, et quittez avec Ctrl + X. Même chose ensuite avec nano Dockerfile.
Étape 2 : écrire la page et la recette
Le premier fichier s’appelle index.html : c’est votre page.
<!doctype html>
<html lang="fr">
<meta charset="utf-8">
<title>Mon image Docker</title>
<style>
body { font-family: system-ui, sans-serif; display: grid; place-items: center;
min-height: 100vh; margin: 0; background: #0b1b2e; color: #fff; }
h1 { color: #5cc8ff; }
</style>
<main>
<h1>Docker fonctionne !</h1>
<p>Version 1.0, construite avec mon propre Dockerfile.</p>
</main>
</html>
Le second s’appelle exactement Dockerfile, avec un D majuscule et sans
extension : c’est la recette.
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
| Ligne | Ce qu’elle fait |
|---|---|
FROM nginx:alpine | Part de l’image officielle de Nginx : tout ce qu’elle contient est hérité |
COPY index.html … | Copie votre page à l’endroit où Nginx va la chercher, et remplace celle d’origine |
EXPOSE 80 | Indique que l’application écoute sur le port 80. C’est une étiquette : elle n’ouvre rien |
Vérifiez que le dossier contient bien les deux fichiers, avec les bons noms :
ls
Étape 3 : construire l’image
docker build -t owlnet-demo:1.0 .
| Morceau | Rôle |
|---|---|
docker build | Lance la construction |
-t owlnet-demo:1.0 | Donne un nom (owlnet-demo) et un tag (1.0) à l’image |
. | Le dossier courant : c’est là que Docker lit le Dockerfile et les fichiers à copier |
Docker affiche chaque étape au fur et à mesure, puis termine sans erreur. Votre image apparaît dans la liste :
docker image ls owlnet-demo
Dans Docker Desktop, la vue Builds garde l’historique de vos constructions,
et Images montre owlnet-demo avec son tag 1.0.
Étape 4 : la lancer
Même principe qu’à l’épisode 3, avec votre image et un autre port :
docker run -d --name owlnet-site -p 127.0.0.1:8081:80 owlnet-demo:1.0
Ouvrez http://127.0.0.1:8081 : c’est votre page qui s’affiche, servie par Nginx.
Comprendre les couches et le cache
Une image n’est pas un bloc unique : c’est une pile de couches. Votre image
reprend telles quelles celles de nginx:alpine, et en ajoute une seule, créée
par le COPY.
Relancez exactement la même construction : elle est instantanée, et chaque étape affiche le mot CACHED. Docker a reconnu que rien n’avait changé.
Cette mécanique donne une règle simple pour écrire un bon Dockerfile : ce qui change rarement en haut, ce qui change souvent en bas. Quand une couche doit être reconstruite, toutes celles qui la suivent le sont aussi.
Étape 5 : publier une version 1.1
Ouvrez index.html, remplacez « Version 1.0 » par « Version 1.1 », enregistrez,
puis construisez avec un nouveau tag :
docker build -t owlnet-demo:1.1 .
docker image ls owlnet-demo
Les deux versions coexistent. Actualisez la page du navigateur : elle affiche toujours 1.0. Un conteneur ne se met jamais à jour tout seul ; on le remplace par un nouveau, créé depuis la nouvelle image :
docker rm -f owlnet-site
docker run -d --name owlnet-site -p 127.0.0.1:8081:80 owlnet-demo:1.1
C’est tout l’intérêt des tags : si la 1.1 posait problème, relancer la 1.0 ne prendrait qu’une commande.
Nettoyer
Supprimez le conteneur de test. Gardez le dossier mon-image : l’épisode 5
s’en sert.
docker rm -f owlnet-site
docker image rm owlnet-demo:1.0 owlnet-demo:1.1
La seconde ligne retire vos deux versions de l’image. Seuls les noms commençant
par owlnet- sont concernés : n’y ajoutez jamais un nettoyage global.
Testez-vous
3 questions pour vérifier que l’essentiel est acquis. Rien n’est noté ni enregistré.
Que désigne le point final de docker build -t owlnet-demo:1.0 . ?
Docker ne lit que les fichiers de ce dossier. C’est pourquoi COPY index.html échoue si le fichier est ailleurs, même s’il existe sur votre disque.
EXPOSE 80 suffit-il à rendre le site accessible depuis votre navigateur ?
EXPOSE documente le port utilisé dans le conteneur, pour les humains et pour les outils. Seul -p, au moment du docker run, ouvre réellement une porte sur votre ordinateur.
Vous relancez la construction sans rien modifier. Pourquoi est-ce instantané ?
Chaque instruction produit une couche. Tant qu’une instruction et les fichiers qu’elle utilise ne changent pas, Docker reprend la couche en cache et l’annonce par le mot CACHED.
Vérifier que tout fonctionne
Cochez au fur et à mesure : quand tout est coché, vous pouvez passer à la suite.
Problèmes courants
« failed to read dockerfile: open Dockerfile: no such file or directory »
Docker ne trouve pas le fichier. Soit le terminal n’est pas dans le dossier mon-image (vérifiez avec pwd), soit le fichier s’appelle en réalité Dockerfile.txt : la commande ls le montre. Renommez-le, sous Windows avec Rename-Item Dockerfile.txt Dockerfile, sous Ubuntu avec mv Dockerfile.txt Dockerfile.
La construction échoue sur la ligne COPY, avec « "/index.html": not found »
Le fichier index.html n’est pas dans le dossier de construction. Il doit se trouver à côté du Dockerfile, et la commande docker build doit se terminer par un point, depuis ce même dossier.
J’ai modifié index.html, mais le navigateur affiche toujours l’ancienne page
Le conteneur en marche utilise toujours l’ancienne image : il ne se met jamais à jour tout seul. Reconstruisez, supprimez l’ancien conteneur, lancez-en un nouveau depuis la nouvelle image. Si ça persiste, forcez l’actualisation du navigateur avec Ctrl + F5.
Je peux oublier le point à la fin de docker build ?
Non. Docker répond qu’il lui manque un argument : ce point est le dossier de construction, c’est-à-dire l’endroit où il va chercher vos fichiers.
Votre progression reste sur cet appareil, rien n’est envoyé.