Decouverte
du Dockerfile

Hello world pas a pas
Fabriquer sa premiere image avec deux lignes de recette

Avant de commencer

Cette decouverte suppose qu'on a deja lance des conteneurs avec docker run. Si ce n'est pas le cas, faire d'abord la Decouverte de Docker avant celle-ci.

Ici, on ne va plus utiliser des images faites par d'autres - on va en fabriquer une. Le fichier qui decrit comment fabriquer une image s'appelle un Dockerfile.

Promesse En quelques minutes, on aura un Dockerfile, on aura construit une image, et on aura lance un conteneur qui execute notre code a nous.

Un Dockerfile, c'est quoi ?

Un Dockerfile est un fichier texte qui contient la recette pour fabriquer une image. Une instruction par ligne, lues de haut en bas.

Trois mots-cles suffisent pour 80 % des cas :

FROM
Sur quelle image de base on construit. C'est toujours la premiere ligne.
RUN
Une commande a executer pendant la construction de l'image.
CMD
La commande a lancer quand un conteneur demarre a partir de l'image.
Etape 1

Preparer le terrain

Une image se construit a partir d'un dossier. Tout ce qui est dans ce dossier est envoye a Docker pendant la construction. On commence par un dossier vide, dedie au projet.

A taper dans le terminal
$ mkdir bonjour-docker
$ cd bonjour-docker

Dans ce dossier, on va creer un fichier nomme exactement Dockerfile - sans extension, avec un D majuscule. Avec n'importe quel editeur de texte.

$ nano Dockerfile
Important Le nom doit etre exact : Dockerfile. Pas dockerfile.txt, pas DockerFile. Docker cherche ce nom precis.
Etape 2

Le Dockerfile minimal absolu

Deux lignes. C'est tout. On part d'Alpine - une mini distribution Linux d'environ 5 Mo - et on lui dit ce qu'il faut afficher au demarrage.

Dockerfile
FROM alpine
CMD ["echo", "Bonjour le monde !"]
FROM alpine
partir de l'image officielle alpine - notre image hereditera de tout ce qu'elle contient
CMD [...]
au demarrage du conteneur, executer echo Bonjour le monde !

Sauvegarder et fermer (dans nano : Ctrl+O, Entree, Ctrl+X).

Etape 3

Construire l'image

Maintenant, on demande a Docker de lire notre Dockerfile et d'en faire une image. La commande docker build fait le travail.

$ docker build -t bonjour .
build
construire une image
-t bonjour
nommer (tag) l'image bonjour pour pouvoir la lancer plus tard
.
le dossier courant - c'est la qu'on cherche le Dockerfile
Ce qu'on devrait voir
[+] Building 2.4s (5/5) FINISHED => [internal] load build definition from Dockerfile => [internal] load metadata for docker.io/library/alpine:latest => [1/1] FROM docker.io/library/alpine:latest => exporting to image => => naming to docker.io/library/bonjour
Etape 4

Lancer notre image

L'image existe maintenant sur la machine. On la lance comme n'importe quelle image.

$ docker run bonjour
Ce qu'on devrait voir
Bonjour le monde !
Bravo Vous venez de fabriquer votre propre image Docker et de l'executer. C'est techniquement la meme chose que ce que font les developpeurs en production - juste plus simple.

Pour confirmer qu'elle existe sur la machine :

$ docker images

Comprendre les couches

Chaque ligne du Dockerfile cree une couche. Les couches s'empilent et forment l'image finale. Chaque couche est mise en cache - si on ne touche pas a une ligne, sa couche est reutilisee telle quelle.

FROM alpine
RUN echo "..." > /m.txt
CMD ["cat", "/m.txt"]
1Couche de base Alpine
2Fichier /m.txt cree
3Commande de demarrage

C'est pour cela qu'on met les choses qui changent peu en haut du Dockerfile, et les choses qui changent souvent en bas - le cache reste utile plus longtemps.

Etape 5

Ajouter une couche - RUN

On modifie le Dockerfile pour qu'il fabrique un fichier pendant la construction, puis l'affiche au demarrage.

Dockerfile
FROM alpine
RUN echo "Salut depuis l'interieur de l'image" > /message.txt
CMD ["cat", "/message.txt"]
RUN
execute pendant la construction - le fichier est ecrit une fois, puis fait partie de l'image
CMD
execute au demarrage du conteneur - lit le fichier deja present
Difference cle RUN modifie l'image (au build). CMD est ce qui s'execute quand l'image devient un conteneur (au run).
Etape 6

Reconstruire et constater le cache

On reconstruit, puis on relance.

$ docker build -t bonjour .
$ docker run bonjour
Ce qu'on devrait voir
Salut depuis l'interieur de l'image

Si on relance docker build une troisieme fois sans rien modifier, la construction est quasi instantanee. Docker reutilise les couches en cache.

[+] Building 0.1s (5/5) FINISHED => CACHED [1/1] FROM docker.io/library/alpine:latest => CACHED [2/2] RUN echo "Salut depuis l'interieur de l'image" > /message.txt
Le mot magique CACHED - c'est ce qu'on veut voir le plus possible.
Etape 7

Bonus - rendre le message dynamique

Avec ENV, on peut declarer une variable d'environnement utilisable au demarrage. Ca donne une image personnalisable sans rebuild.

Dockerfile
FROM alpine
ENV NOM=monde
CMD echo "Bonjour $NOM !"

Reconstruire puis lancer normalement :

$ docker build -t bonjour .
$ docker run bonjour
Bonjour monde !

Et avec une valeur differente, sans toucher au Dockerfile :

$ docker run -e NOM=Matane bonjour
Bonjour Matane !

Les trois mots-cles a retenir

FROM
Image de base. Toujours en premier. Choisir une image legere quand on peut (alpine, debian-slim).
RUN
Execute pendant la construction. Sert a installer, copier, configurer. Cree une couche.
CMD
Execute au demarrage du conteneur. Une seule par Dockerfile - c'est le programme principal.

Avec ces trois instructions plus docker build et docker run, on peut fabriquer la majorite des images simples qu'on rencontre dans un cours, un projet personnel ou un prototype.

Pour aller plus loin

Le devoir final demande des Dockerfiles plus riches. Les briques suivantes y seront utiles.

COPY
Copier des fichiers du dossier de build vers l'interieur de l'image. Indispensable pour amener son code applicatif.
WORKDIR
Definir le dossier de travail dans l'image. Toutes les commandes suivantes s'executent depuis la.
EXPOSE
Documenter quel port le conteneur utilise. Pratique pour les images qui exposent un service web.
Le devoir final
L'evaluation reprend ces concepts pour fabriquer un conteneur web et un conteneur applicatif personnalises.