image docker
Une image est une tarball avec une promesse.
Cette promesse est la suivante : lance-moi, et tu obtiendras exactement la même application, sur chaque machine qui fait tourner Docker. Code, runtime, bibliothèques système, paramètres — tout est dedans, figé dans un paquet en lecture seule que plus personne ne peut modifier. Ni toi, ni ton collègue, ni le serveur où il arrive par accident.
Ce que tu peux faire, en revanche, c'est ajouter quelque chose par-dessus. Une image Docker est composée de couches, et chaque couche représente la différence avec la couche en dessous. Tu installes nginx, une couche s'ajoute. Tu copies ton code applicatif, encore une couche. Tu supprimes un fichier, tu poses une couche avec une marque de suppression par-dessus la couche où ce fichier se trouve encore.
C'est le principe du copy-on-write, et c'est la raison pour laquelle les images sont si efficaces. Dix images qui tournent toutes sur `alpine` partagent cette même couche de base. Ton disque paie une seule fois pour la base, pas dix fois. Et si tu tires une image que ton voisin a déjà récupérée, Docker ne télécharge que les couches que tu n'as pas encore.
Tout en bas se trouve toujours une image de base : `alpine`, `ubuntu`, `debian`. Tu construis par-dessus avec un Dockerfile, où chaque instruction produit une nouvelle couche. L'image elle-même ne change plus jamais par la suite. Tu veux un correctif de sécurité ? Tu construis une nouvelle image avec une nouvelle couche. L'ancienne reste, identifiable via son digest, une empreinte digitale du contenu.
Cette immuabilité n'est pas une limitation, c'est la garantie que ce que tu testes en développement est aussi ce qui tourne en production.
La gestion se fait via les sous-commandes `docker image`. `docker image ls` affiche ce qui se trouve en local : repository, tag, ID d'image, taille, date de création. Ajoute `--all` et tu verras aussi les images dangling — des couches orphelines qui restent après un rebuild. Elles prennent de la place et ne font rien d'autre.
`docker image inspect` donne l'histoire complète en JSON : architecture, système d'exploitation, la structure complète des couches, la `CMD` qui s'exécute dès que tu démarres un conteneur. Avec `--format`, tu en extrais un seul champ, par exemple `{{ .Size }}` si tu veux seulement la taille. La sortie est détaillée, mais si tu sais où chercher, c'est plus rapide qu'une interface graphique.
`docker image history` raconte comment l'image a été créée, couche par couche. Quelle commande a créé quelle couche, quand, et quelle est la taille de cette couche. Utile pour repérer une image devenue inutilement volumineuse — généralement, il y a un `apt-get install` sans `clean` entre les deux.
Le partage d'images se fait via un registre, public ou privé. Mais parfois, tu veux transporter une image vers une autre machine sans réseau. `docker image save -o myapp.tar myapp:latest` empaquette l'image, y compris toutes les couches et tags, dans un seul fichier tar. De l'autre côté, `docker image load -i myapp.tar` la récupère. Pas besoin de registre, pas besoin d'internet, juste une clé USB ou une commande `scp`.
Fais attention à la différence avec `docker image import`. Celle-ci lit une tarball d'un système de fichiers et en fait une image avec une seule couche. La structure de couches et l'historique d'origine sont perdus. Import est pour la migration d'environnements existants, pas pour transférer tes propres images. Pour cela, utilise save et load.
Les tags sont des noms, pas des versions. `docker image tag myapp:latest myapp:v1.2` ne change rien à l'image, cela ajoute seulement un alias. Deux noms qui pointent vers la même image, avec le même ID d'image. C'est un moyen pratique de préparer une image pour un registre sans la reconstruire.
Une image peut desservir plusieurs architectures à la fois via des manifests. Un seul nom, plusieurs variantes : `linux/amd64` pour ton serveur, `linux/arm64` pour ce Raspberry Pi. Docker choisit automatiquement la bonne variante lors d'un `docker pull`. Tu n'as plus besoin de te rappeler quelle architecture tourne où.
Le choix n'est pas de savoir si tu utilises des images, mais comment tu les construis. Une image avec tout dedans est facile, mais volumineuse et difficile à maintenir. Une image avec seulement le runtime minimal est plus rapide et plus sûre, mais exige que tu comprennes ce dont ton application a besoin. L'équilibre entre commodité et contrôle, c'est toi qui le détermines, couche par couche.
Quoi que tu choisisses, l'image est le seul artefact qui survit au voyage de ton ordinateur portable au serveur de production sans changer en cours de route. Ce n'est pas un luxe. C'est la base sur laquelle tu peux compter pour que ce qui tourne là-bas soit bien ce que tu as construit.