Docker - Les Images

by Tyleo Dv. Delaware

Share

Sous Docker, les conténaires sont basés sur des images. La conception d'Images est donc la source de création des conténaires plus tard. Cette page rentre plus en détail sur ces fameuses images.

Le Dockerfile

Il s'agit d'un fichier, conventionnellement nommé "Dockerfile" mais que l'on peut techniquement nommer comme l'on le veut. Voici un exemple de Dockerfile basique, ici cette image fait tourner Code Server avec Debian sur le tag Latest :

# Image Source (base) sur Ubuntu Noble 24.04 LTS
FROM debian:latest

# Maj des packages et upgrade intégrale
RUN apt-get update
RUN apt-get upgrade -y

# Installation des dépendances et outils utiles
RUN apt-get install -y bash git curl wget btop htop fish zsh nala ncdu

# Installation de Code Server (automatique depuis https://github.com/coder/code-server)
RUN curl -fsSL https://code-server.dev/install.sh | sh

# Vars
ENV PASSWORD 123+aze

# Patch du fichier /root/.config/code-server/config.yaml
# Diffusion auto sur 0.0.0.0 (no filter) et sur le port défini par variable.

COPY ./Custom-Code-Server/run-code /bin
RUN chmod +x /bin/run-code
CMD [ "sh", "-c", "/bin/run-code ${PASSWORD}" ]

Les Instructions

Sont toujours indiquée en UPPERCASES (MAJUSCULES) suivi des arguments de l'Instruction. le FROM est obligatoire.

#

Commentaire, pour dire tout ce que vous souhaitez. Ne pas perdre l'habitude de commenter !

FROM

Il s'agit de la première ligne du fichier, il indique l'image source utilisée pour créer l'image en cours de conception. Cette Instruction n'est générallement présente qu'une seule fois et au début du fichier.

Mais en effet, avec la méthode du Multi Staging, il est possible d'en mettre plusieures les unes sur les autres (Stacking) et ainsi accumuler les images et leurs définitions propres.

COPY

Instruction qui permet de copier un fichier du filesystème en cours vers l'intérieur de l'image. Utile pour injecter un fichier, dossier ou même un dépôt Git entier.

RUN

Instruction qui permet d'executer des commandes qui auront de l'effet dans l'image en cours de conception. Permettant de construire les dépendances, les packages et données. Elle permet aussi d'executer des scripts injectés par un ADD ou un COPY.

CMD

Instruction qui permet de définir la commande qui se lancera avec le conténaire et le maintiendra actif. Cette définition n'est présente qu'une fois et générallement a la fin du Dockerfile (mais pas forcement).

La définir plusieures fois n'a aucun effet, hormis que seule la dernière sera prise en compte.

ENV

Instruction qui permet de définir des variables et leurs valeurs par défaut. Il n'est pas obligatoire de définir une variable pour qu'elle soit injectée via une Composition ou une commande Run ou Exec depuis le CLI/Shell Docker.

Si la variable est définie dans le Dockerfile, la valeur sera par défaut définie mais sera réinscriptible via les commandes docker et les composes.

ARG

Instruction qui permet de définir les arguments spécifique de build d'image.

ENTRYPOINT

Instruction qui permet de définir une commande ou un script a executer une seul fois au premier démarrage du conténaire, cette commande ne s'execute qu'après la création de ce dernier.

EXPOSE

Instruction qui permet de définir des ports a exposer quand les applications ne le font pas déjà. Cela force l'exposition (ouverture du port au niveau du conténaire, cela n'expose pas le port sur l'hôte et dépend toujours de la secion ports: des composes !).

HEALTHCHECK

Instruction qui permet de définir comment vérifier la santé du conténaire. Si non défini, alors l'état sera toujours HEALTHY. Il s'agit d'une commande executée réguliérement par Docker, dans le conténaire.

LABEL

Instruction pour ajouter des métadonnées a l'image. Utile pour intégrer des données informationnelles importantes ou des signatures internes.

MAINTAINER

Défini l'auteur de l'image, sorte de signature d'auteur dans l'image même.

SHELL

Définition qui permet de définir le shell par défaut dans l'image, utilisable plusieures fois pour changer de shell dans le Dockerfile. Le dernier SHELL devient le Shell par défaut final du conténaire créé après.

STOPSIGNAL

Définition qui permet de définir a quel signal système (SYSCALL) le conténaire devrait réagir et s'arréter. Utile pour de l'automation par exemple.

WORKDIR

Permet de changer d'emplacement pour les définitions RUN, COPY etc... Le dernier WORKDIR devient le premier dossier au démarrage du conténaire.

VOLUME

Définition qui permet de définir des volumes créables par le conténaire. Générallement, ceci n'est pas défini mais peut servir a préparer le volume avant montage.

USER

Définition qui permet de définir le User d'execution pour le futur conténaire. Il est déconseillé d'utiliser Root/0 (hormis dans les cas particuliers ou rien d'autre ne fonctionne, évidemment.

Lancer un Build en mode courant

docker build .

Cette commande construit une image avec un Dockerfile présent au même niveau.

⚠️
Attention : Sans aucun autre paramètre, l'image ne sera, ni taguée, ni nommée, et ne pourra être pusher vers un serveur !

Lancer un Build avec Tag

docker build . -t final.repo/monimage:version1

Ici, on tag l'image en définissant :

💡
Peut être une IP, un Nom DNS etc... mais si SSL n'est pas actif sur le serveur, il faudra autoriser celui ci dans le démon Docker (https://docs.docker.com/reference/cli/dockerd/#insecure-registries)
💡
Ne pas définir de tag a pour effet de taguer automatiquement sur :latest. Pratique quand on veux un seul fil de releases.
💡
Définir un autre tag, comme ici, permet de créer un autre fil de releases ou une variante d'image. Exemple :

- Je fait une image avec Ubuntu et Code Server
- Je souhaite faire une variante avec Fedora 40

Je met donc un tag :fedora-40-code (par exemple) et adapte mon Dockerfile (ou sur un nouveau, pour rappel il peut être nommé comme on veux !) et utilise la commande de la section suivante de cette page.

Lancer un Build avec un Dockerfile Variante

Cela permet d'avoir plusieurs Dockerfiles dans un dossier et gérer les variantes d'une même image. Permet ainsi de créer ces variantes sans créer plusieurs noms d'images et ainsi gérer les versions sans difficultés.

docker build . -t final.repo/monimage:version1 -f ./dir/Dockerfile.fedora-code

Faire l'Envoi vers le Serveur de Registre (Dépôt)

Le nom complet de l'image détermine le serveur cible, il suffit donc de faire `docker push final.repo/monimage:version1` et ainsi :

De manière générale, Docker utilise les mêmes logiques que Git. Evidemment, si le dépôt requère une connexion utilisateur, il faudra d'abord faire `docker login final.repo` et s'identifier.

Les dépôts personnels privés peuvent utiliser Basic Auth HTTP (docker login le gère sans problème).

Infos pour créer son registre

Le Compose pour le Registre :

GitHub - maxmasetti/docker-compose-registry: A local docker registry cache to lower bandwidth required when install several similar container.
A local docker registry cache to lower bandwidth required when install several similar container. - maxmasetti/docker-compose-registry

Le Compose pour l'Interface Web (sans authentification par défaut !)

GitHub - Joxit/docker-registry-ui: The simplest and most complete UI for your private registry
The simplest and most complete UI for your private registry - Joxit/docker-registry-ui

La Gateway conseillée pour le basic auth :

GitHub - tobychui/zoraxy: A general purpose HTTP reverse proxy and forwarding tool. Now written in Go!
A general purpose HTTP reverse proxy and forwarding tool. Now written in Go! - tobychui/zoraxy

Et tout le reste, au passage 😄