DOCKERFILE

Simple fichier texte composé d'un ensemble de commandes ou d'instructions à exécuter, il permet de créer une image docker à partir d'une image de base. Des couches supplémentaires sont ajoutées étapes par étapes pour la création d’une image Docker. Ce processus s’intitule le build process. Il définit à quels répertoires et fichiers le build process aura accès. La création de Dockerfile se fait à l’aide des commandes CLI.
Pour créer une image à l'aide d'un dockerfile, celui-ci est généralement placé à la racine du conteneur et sera lancée par la commande suivante :

docker build -t NomImage:version .    # . représente la racine du conteneur ou ./CheminDockerfile

EMPLACEMENT

mon_projet/
├── src/
├── Dockerfile
└── README.md

INSTRUCTION


INSTRUCTION DESCRIPTION COMMENTAIRE
FROM Définir l’image de base Doit apparaître comme la première instruction
une seule entrée par stade de build
LABEL
ARG Déclare les paramètres de ligne de commande
pour le build process
Peut apparaître avant l’instruction
FROM
ENV Définit les variables d’environnement pour le build
process et le container runtime
RUN Exécute la commande dans l’image
durant le build process
Crée une nouvelle couche
EXPOSE Définit les assignations de port
pour le conteneur exécuté
Les ports doivent être exposés
lors du lancement du conteneur
USER Modifie le statut de membre
de l’utilisateur et de groupe
ENTRYPOINT Définit la commande par défaut
pour le lancement du conteneur
Une seule entrée par stade de build
CMD Définit les arguments par défaut
pour le lancement du conteneur
Une seule entrée par stade de build
COPY Copie les fichiers et répertoires sur l’image Crée une nouvelle couche
ADD Copie les fichiers et répertoires sur l’image Crée une nouvelle couche
utilisation déconseillée
WORKDIR Modifie le répertoire actuel
VOLUME Inclut le répertoire dans l’image en tant que volume
lors du lancement du conteneur dans le système hôte
Ligne 1 Col 3
SHELL Change le shell dans le conteneur

FROM

L’instruction FROM définit l’image de base sur laquelle les instructions opèrent. Cette instruction ne peut exister qu’une fois par stade de build et doit apparaître dans la première instruction. Attention : l’instruction ARG peut apparaître avant l’instruction FROM. Nous pouvons ainsi spécifier exactement quelle image est utilisée en tant qu’image de base via un argument de ligne de commande lorsque nous lançons le build process.
Chaque image Docker doit être basée sur une image de base. En d’autres termes, chaque image Docker possède exactement une image parent.

FROM python:3.8-slim-buster
FROM python:lasted

LABEL

Ajoute des métadonnées à l'image avec un système de clés-valeurs, permet par exemple d'indiquer à l'utilisateur l'auteur du Dockerfile, son adresse mail …
Son utilisation est la suivante :

LABEL <key1>=<value1> <key2>=<value2> <key2>=<value2> ...

Exemple :

# Ajoute la référence du commit à partir duquel l'image est créée
ARG vcs-ref=unknown
LABEL vcs-ref=$vcs-ref

# Ajoute l'auteur de l'image
LABEL maintainer="John Doe <john@doe.com>"

Il est possible ensuite d’afficher les labels d’une image via la commande suivante :

docker inspect --format='{{json .Config.Labels}}' my-image

Ainsi que de filtrer les images par label :

docker images --filter "label=maintainer=John Doe <john@doe.com>"

ENV

L'instruction ENV définit une variable d'environnement dans la nouvelle image. Une variable d'environnement est une paire clé-valeur, accessible à n'importe quel script ou application. Les applications Linux utilisent beaucoup les variables d'environnement pour une configuration initiale utilisables dans le dockerfile et dans le conteneur. ENV est une variable d'environnement accessible depuis le Dockerfile et votre conteneur.

ENV <clé> <valeur>

<clé> représente la variable d'environnement qui va être définie.
<valeur> représent la valeur qui va être attribuée à la variable d'environnement.

# donner à la variable 'user' la valeur 'admin'
ENV user="admin"
ENV LOGGING=true
ENV APP_NAME=my_app

Les instructions ENV et ARG permettent de stocker des variables d'environnement. La seule différence, est que nous pouvons utiliser l'instruction ARG en tant que variable temporaire, utilisable qu'au niveau de votre Dockerfile. A l'inverse l'instruction ENV est une variable d'environnements accessible depuis le Dockerfile et votre conteneur.
Nous privilégons ARG, si vous avez besoin d'une variable temporaire et ENV pour les variables persistantes.

RUN

L'instruction RUN fait partie des instructions principales de Dockerfile. Elle peut exécuter n'importe quelle commande dans notre image. Chaque instruction du Dockerfile va se transformer en layer. Il est recommandé de regrouper toutes les instructions RUN dans une seule et même instruction.
Il existe deux formes pour cette commande :

  • La forme “shell” : La commande est exécutée dans un shell (/bin/sh -c par défaut sous Linux ou cmd /S /C sous Windows). Cela permet d’utiliser toutes les fonctionnalités du shell : pipe, redirection, chaînage de commandes, substitution de variables, etc.
  • La forme “exec” : Elle exécute simplement le binaire que vous fournissez avec les arguments que vous incluez, mais sans aucune fonctionnalité d’analyse du shell.
# Forme shell
RUN <command>

# Forme exec
RUN ["executable", "param1", "param2", "..."]
RUN apt-get update && apt-get install git
RUN npm ci
RUN ["npm", "run", "build"]

EXPOSE

Les conteneurs Docker communiquent à travers le réseau. Les services exécutés dans le conteneur sont adressés via des ports spécifiés. L’instruction EXPOSE documente les assignations de ports et supporte les protocoles TCP et UDP. Le service sera exposé qu'au communication inter-conterneurs (à l'intérieur du docker). Ces ports seront donc accessibles par d’autres services connectés au même réseau, mais ne seront pas publiés sur la machine hôte.À titre alternatif, il est possible d’écraser les ports sélectionnés avec « docker run -p » :

dockerfile
EXPOSE <numero_port>/<protocole> 
EXPOSE 80/udp
EXPOSE 5000-6000
docker run --expose=5000-6000
# Exposer une plage de port
docker-compose
Version:"3"
...
...
services:
  myapp1:
    ...
    expose:
      - "3000"                          
      - "3001-3005"  # plage ports (3001-3005) disponible   

<protocole> est un champ facultatif permettant de spécifier un protocole de transport spécifique, tel que TCP et UDP. Si aucun protocole de transport n'a été spécifié, alors TCP est supposé être le protocole de transport. Les chemins suivants sont alors disponibles pour activer les ports lorsque le conteneur est lancé.

PUBLISH

services:
  myapp1:
    ...
    ports:
      - "8000:8000"            # port conteneur 8000, assigné au port hôte 8000
      - "9090-9190:8080-8180"  # plage ports hôte 8080-8081, lié à plage ports 9090-9091
      - "192.168.2.17:8002:8002"  # Port TCP 80 du conteneur vers le port 8002 de l’hôte pour les connexions à l’adresse IP hôte 192.168.2.17. Par défaut, Docker lie les ports de conteneur publiés à l’adresse IP 0.0.0.0, qui correspond à n’importe quelle adresse IP du système.
      - "1960:6060/udp"        # Port UDP du conteneur 1960 lié au port hôte 6060.

USER

Cette instruction définit l’utilisateur (UID) et éventuellement le groupe d’utilisateurs (GID) à utiliser lors de l’exécution de l’image, mais également pour toutes les instructions RUN, CMD et ENTRYPOINT qui la suivent dans le Dockerfile :

USER <user>[:<group>]
USER <UID>[:<GID>]

Exemple :

# Pensez à vérifier la documentation si un utilisateur
est déjà renseigner :

USER karl

# Ou vous pouvez créer un nouvel utilisateur
ARG USERNAME=newuser
ARG USER_UID=1000
ARG USER_GID=$USER_UID

RUN groupadd --gid $USER_GID $USERNAME \
    && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME

USER $USERNAME

ENTRYPOINT

Comme son nom l'indique, c'est le point d'entrée de votre conteneur, en d'autres termes, c'est la commande qui sera toujours exécutée au démarrage du conteneur. Il prend la forme de texte ou de tableau JSON :

ENTRYPOINT ["cmd1","cmd2"]
ENTRYPOINT ["/bin/chamber", "exec", "--help"]

CMD

L'instruction CMD peut exécuter n'importe quelle commande à la manière de l'instruction RUN. Cependant, la différence majeure entre ces deux, c'est le moment de l'exécution. La commande fournie via l'instruction RUN est exécutée pendant la construction de l'image, tandis que la commande spécifiée par l'instruction CMD est exécutée lorsque le conteneur est lancé. Elles spécifie les arguments qui seront envoyés au ENTRYPOINT, (on peut aussi l'utiliser pour lancer des commandes par défaut lors du démarrage d'un conteneur). Si il est utilisé pour fournir des arguments par défaut pour l'instruction ENTRYPOINT, alors les instructions CMD et ENTRYPOINT doivent être spécifiées au format de tableau JSON.

CMD ["/bin/service", "-d"]

CMD et ENTRYPOINT

Ce qui différencie ces deux commandes est que CMD permet d’exécuter une action sans avoir besoin de paramètres supplémentaires tandis que ENTRYPOINT est inchangeable et exécute la même action tout le long de l’activation du conteneur. Dans ce cas, il agit comme un fichier exécutable.

Voici un exemple d’instructions:

ENTRYPOINT [‘echo’, ‘hello’, ‘world’]
CMD [echo ‘hello world’]

Ces deux commandes donnent les mêmes résultats, c’est pour cela que, parfois, on n’utilise qu’une seule d’entre elles, malgré le fait que l’on peut tout à fait les utiliser ensemble. L'utilisation de CMD est plus souvent préférée. Par défaut c’est l’utilisateur root qui sera propriétaire des fichiers ou répertoire copiés, mais il est possible de modifier celui-ci via l’option –chown=<user>:<group>.

COPY

Cette instruction comme son nom l’indique permet de copier des fichiers ou répertoires d’une source vers une destination :

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

ADD

Cette instruction est similaire à COPY à la différence que la source peut être une URL ou une archive (tar) que la commande décompresse :

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

Exemple :

# myApp.tar.gz sera décompressé dans /app/
ADD myApp.tar.gz /app/

# Le fichier sera téléchargé et décompressé dans /tmp/
ADD http://example.com/data.tar.gz /tmp/

WORKDIR

Cette instruction définit le répertoire de travail pour toutes les instructions RUN, CMD, ENTRYPOINT, COPY et ADD qui le suivent dans le Dockerfile. Si le répertoire n’existe pas, celui-ci sera créé.

WORKDIR /path/to/workdir

Exemple :

# On se déplace dans le répertoire /opt
WORKDIR /opt

# Créer le dossier my-app dans /opt et se déplace dans celui-ci
WORKDIR my-app

VOLUME

L’instruction VOLUME définit un « point de montage » à l’intérieur du conteneur.
Un répertoire « partagé » est créer dans le répertoire au plus haut niveau de l’image. Nous spécifions qu'un répertoire doit être monté dans le système hôte lorsque le conteneur est lancé :

VOLUME ["<path>", ...]
VOLUME <path> [<path> ...

Exemple :

VOLUME ["/data"]
VOLUME /var/log /var/db /Data

Nous ne pouvons pas spécifier l’itinéraire réel du système hôte à l’intérieur du Dockerfile. Par défaut, les répertoires définis par l’instruction VOLUME sont montés sur le système hôte sous « /var/lib/docker/volumes/ ».

SHELL

Cette instruction permet de changer le shell utilisé pour toutes les instructions utilisant le format shell (CMD, ENTRYPOINT et RUN) :

SHELL ["executable", "parameters"]

Exemple :

FROM ubuntu
RUN echo "/bin/sh est par défaut"
SHELL ["/bin/bash", "-c"]
RUN echo "Nous utilisons maintenant /bin/bash par défaut"

EXEMPLE

FROM webdevops/php-apache
LABEL mainteneur= "Karl DEGNACE <degnace.info@gmail.com>" 
RUN apt-get update \
&& apt-get clean \


Source : https://www.codeheroes.fr/2022/03/15/docker-conteneuriser-son-application/