Dockerfile

Jusqu’à présent, on a récupéré et construit des images Docker à la main pour créer des containers. Mais on peut également faire la même chose de manière scriptée, avec un fichier — un Dockerfile.

Qu’est ce qu’un Dockerfile

Un fichier Dockerfile est un petit programme conçu pour décrire comment créer une image Docker:


Mise en cache

Lorsqu’on construit l’image, chaque commande du Dockerfile est exécutée dans un nouveau container qui est arrêté à la fin de la ligne. Chacun de ces containers est mis en cache (on parle de layer), cela économise énormément de temps lorsqu’on teste l’installation mais peut prendre de la place si vous ne les nettoyez jamais. Si vous voulez télécharger à nouveau la dernière version d’un fichier (outrepasser le cache), vous devrez le faire explicitement avec no-cache=true.

Si vous modifiez votre Dockerfile et relancez le build, Docker ignorera les lignes qui n’ont pas été modifiées depuis le dernier build, et utilisera les containers en cache — il est donc prérérable de mettre les commandes que vous risquez de modifier le plus à la fin du Dockerfile.


Contexte du build

Le contexte peut être le répertoire qui contient le Dockerfile ou un autre. Tous les fichiers qui se trouvent dans ce dossier seront ajoutés au système de fichiers crée lorsque l’image est crée, et seront accessibles à l’intérieur du Dockerfile (commandes ADD et COPY).

Si vous spécifiez un contexte de compilation arbitraire, disons votre répertoire personnel — où se situe quelques giga de fichiers vidéos, et que vous lancez docker build alors ces fichiers seront inclus dans l’image. Cette image sera énorme, à cause des quelques giga de fichiers vidéos que vous avez involontairement ajoutés à l’image.


Bonnes pratiques


Réduire les layers

Une image est construite à partir de multiples layers — visibles via la commande docker image history IMAGE_NAME — qui prennent de la place.

Pour réduire une image à un seul calque, et ainsi réduire la taille de l’image, on peut


Syntaxe Dockerfile

FROM

La première ligne d’un Dockerfile (hors commentaire) doit spécifier à partir de quelle image démarrer:

FROM busybox

Vous pouvez mettre plusieurs instructions FROM dans votre Dockerfile, pour créer plusieurs images.

CMD

CMD définit la commande par défaut à exécuter lorsqu’un container est démarré. Deux formes sont acceptées:

ENTRYPOINT

ENTRYPOINT ressemble beaucoup à CMD mais ne spécifie que le début de la commande à exécuter lors du démarrage du container, et permet de spécifier la suite lors de l’appel.

ENTRYPOINT ls

Si votre container fonctionne comme un programme de ligne de commande, vous pouvez utiliser ENTRYPOINT pour récupérer les arguments. Accepte la forme shell et la forme exec.

RUN

RUN exécute une commande au moment du build, attend qu’elle se termine et sauvegarde le résultat.
Accepte la forme shell et la forme exec.

RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
RUN unzip install.zip /opt/opt/

Les variables d’environnements, définies avec export, ne sont pas conservées (puisque chaque commande est exécutée dans un container à part). Pour persister une variable d’environnement sur toutes les lignes, il faut utiliser la commande ENV.

ENV

ENV permet de définir des variables d’environnement — qui valent pendant le build et lors de l’exécution du container.

ENV DB_HOST=db.production.example.com
ENV DB_PORT=5432

ARG

ARG définit une variable dont l’utilisateur peut modifier la valeur au moment de lancer le build — avec build-arg.

LABEL

Une instruction LABEL ajoute des métadatas à une image, sous forme de paire clé-valeur.
On peut en définir plusieurs à la fois.

# Nginx
#
# VERSION 0.0.1

FROM ubuntu
LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0"
LABEL maintainer="SvenDowideit@home.org.au"

Ces données sont visibles lorsqu’on lance la commande docker inspect.

docker inspect 7c56cc7c2c0b --format '{{json .Config.Labels}}'
# {"localcloud9":"1"}

On peut également filtrer la liste des containers selon un label donné.

docker ps -a --filter 'label=localcloud9=1'

EXPOSE

EXPOSE liste les ports qui doivent être exposés.
Ces ports ne sont exposés que sur le réseau privé du container.
Il faut toujours utiliser -p au moment de lancer docker run pour exposer les ports en dehors.

EXPOSE 8080 8081

ADD

ADD permet d’ajouter un fichier dans l’image. Ce peut être

Si la destination fini avec un slash, Docker copiera le contenu du fichier vers la destination et non juste le fichier.
Ainsi ADD mydir /home crée le dossier mydir dans le home directory tandis que ADD mydir /home/ copie mydir et tout son contenu récursivement.

COPY

COPY d’ajouter un fichier (local uniquement) dans l’image

COPY run.sh /run.sh

VOLUME

VOLUME définit les volumes persistents ou éphèmères à utiliser (selon que vous passiez deux chemins ou un seul).

# persistent
VOLUME ["/host/path", "/container/path"]
# éphémère
VOLUME ["/shared-data"]

Vous devriez généralement éviter d’utiliser des volumes persistents avec Dockerfile, car cela signifie qu’il ne marchera que sur votre ordinateur.

WORKDIR

WORKDIR définit le répertoire courant pour les commandes qui suivent dans le Dockerfile — c’est comme si vous tapiez cd au début de chaque expression RUN. C’est aussi le répertoire courant lorsqu’on lance un container.

WORKDIR /install/

USER

USER définit avec quel utilisateur les commandes du container doivent être exécutées.
On peut passer le nom ou l’id de l’utilisateur.

USER www-data
USER 1000

SHELL

SHELL définit le shell par défaut pour les commandes exécutées lors du build.
Le shell par défaut sous Linux est [“/bin/sh”, “-c”].

SHELL ["/bin/bash", "-c"]

Dockerfile reference