Docker Cheatsheet

Choose from our wide range of portfolio layouts

Docker Cheatsheet

Installation de Docker sur une Debian

# Mettre à jour la liste de paquet, et autoriser le téléchargement de paquet via https
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release

# Ajouter la clé GPG officiel de docker.
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# Ajoute d'une nouvelle source de paquet (repository) au système APT, .
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Installation de docker.
sudo apt update && sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Vérifier si docker est correctement installé.
sudo docker run hello-world

 

Utiliser docker sans passer par sudo :

Pour utiliser docker avec votre compte utilisateur sans écrire à chaque fois sudo, vous devez ajouter votre compte utilisateur au groupe docker :

usermod -aG docker nom_utilisateur

Dockerfile :

Pour saisir le concept de Dockerfile, concentrons-nous sur deux catégories d’images Docker :

  • Images de base : Ces images sont téléchargées (pull) depuis Docker Hub et stockées localement. Elles incluent les configurations établies par leur créateur.
    Lorsqu’on exécute une commande docker run, Docker télécharge automatiquement l’image requise si elle n’est pas déjà présente localement. Ce processus de téléchargement est implicite, suivi de l’exécution de l’image.
  • Images personnalisés : ce sont des images créer (build) à partir d’un dockerfile. Ce dernier contiendra donc les paramètres de cette image.
    à la création (build) :

    • L’image peut être téléchargée (pull) au préalable, puis personnalisée.
    • L’image peut déjà être présente localement, auquel cas elle sera personnalisée puis reconstruite.

Lorsqu’on utilisee la commande FROM ubuntu:latest dans un Dockerfile, Docker va d’abord chercher l’image ubuntu avec le tag latest dans notre stockage local. Si l’image n’est pas trouvée localement, Docker va ensuite la télécharger automatiquement depuis Docker Hub, le dépôt public de Docker.

FROM <nom_image:version>       
MAINTAINER <email>   
ARG <version>=<valeur>
COPY <src-fichier-host> <dst-fichier-docker>    
RUN <command>  
USER <username> 
WORKDIR <dir>   
CMD <command> 
ENTRYPOINT <command>
ENV <env-name> <env-value>

  1. FROM ubuntu:latest :
    • Fonction : Définit l’image de base sur laquelle l’image Docker sera construite. Ici, cela signifie que l’image sera basée sur la dernière version d’Ubuntu disponible.
    • Utilisation : Choisir la bonne image de base est crucial, car cela détermine l’environnement sous-jacent et les logiciels disponibles pour les étapes suivantes.
  2. LABEL maintainer= »lotfi@geekologue.com » :
    • Fonction : Ajoute une étiquette à l’image Docker pour indiquer le mainteneur de l’image.
    • Utilisation : C’est utile pour la documentation et l’organisation, permettant à d’autres utilisateurs ou à vous-même de savoir qui est responsable de l’image.
  3. ARG NODE_VERSION=14 :
    • Fonction : Déclare une variable de build nommée NODE_VERSION avec une valeur par défaut de 14. Cette variable est utilisée lors de la construction de l’image Docker.
    • Utilisation : Permet de personnaliser la version de Node.js utilisée dans l’image Docker. La valeur de NODE_VERSION peut être remplacée par une autre version en utilisant --build-arg NODE_VERSION=<version> lors de l’exécution de docker build.
  4. COPY ./monscript.sh /usr/local/bin/monscript.sh :
    • Fonction : Copie le fichier monscript.sh de votre système de fichiers local dans l’image Docker à l’emplacement spécifié.
    • Utilisation : Utile pour ajouter des scripts ou des fichiers de configuration nécessaires au fonctionnement de votre application ou service dans le conteneur.
  5. RUN apt-get update && apt-get install -y nginx :
    • Fonction : Exécute des commandes pour mettre à jour la liste des paquets et installer Nginx dans l’image Docker.
    • Utilisation : Cette commande est utilisée pour installer des logiciels ou des dépendances nécessaires à votre application.
  6. USER www-data :
    • Fonction : Définit l’utilisateur sous lequel les commandes suivantes seront exécutées et sous lequel le conteneur s’exécutera.
    • Utilisation : Améliore la sécurité en s’assurant que le conteneur ne s’exécute pas avec des privilèges root, ce qui est important pour limiter les risques de sécurité.
  7. WORKDIR /var/www :
    • Fonction : Définit le répertoire de travail pour les commandes RUN, CMD, ENTRYPOINT, COPY, et ADD.
    • Utilisation : Cela permet de définir le répertoire dans lequel les commandes seront exécutées et où votre application sera probablement située.
  8. CMD [« nginx », « -g », « daemon off; »] :
    • Fonction : Définit la commande par défaut qui sera exécutée au démarrage du conteneur.
    • Utilisation : Cette commande est généralement utilisée pour exécuter l’application ou le service principal du conteneur. Ici, elle démarre Nginx avec une configuration spécifique.
  9. ENTRYPOINT [« /usr/local/bin/monscript.sh »] :
    • Fonction : Définit une commande ou un script qui sera toujours exécuté au démarrage du conteneur.
    • Utilisation : Il est utilisé pour configurer un conteneur comme un exécutable ou pour exécuter un script de démarrage nécessaire.
  10. ENV MY_ENV_VAR valeur :
    • Fonction : Définit une variable d’environnement dans l’image Docker.
    • Utilisation : Ces variables peuvent être utilisées pour configurer le comportement de votre application, passer des paramètres dynamiques, etc.

Tips et cas pratique

Certaines actions nécessitent des privilèges, a fin de na pas écrire notre mot de passe dans un dockerfile, nous allons opter pour la déclaration via la variable d’environnement :

Voici le principe

Dans le dockerfile :

ENV PASSWORD=default_value

 

Après le build, au moment du lancement du docker nous déclarons notre variable d’environnement :

docker run -e PASSWORD=Pa$$w0rd jcg:1.0


Et voilà un exemple concret :

Création d’un dockerfile :

Contenu du dockerfile :

#déterminer l’image de base que l’on veut utiliser :
FROM debian:latest

#Renseigner le mainteneur de l’image :
LABEL maintainer= »lotfi@geekologue.com »

#Création d’une variable d’environnement pour stocker notre mot de passe via un  « docker run »
ENV PASSWORD=default_value

#Copie du fichier jcg.sql qui se trouve dans le même dossier que le dockerfile vers le dossier /data du conteneur:
COPY ./jcg.sql /data/

#Exécution d’un apt update.
#Ajout d’un utilisateur geekologue avec un uid 1000.
#Fournir un mot de passe à l’utilisateur geekologue grâce à la variable d’environnement (nous déclarons le mot de passe plus tard lors du lancement du docker).
#Création d’un dossier lotfi dans le dossier data du conteneur.
#changement du propriétaire du dossier /data/lotfi.
RUN apt update && \
useradd -u 1000 geekologue && \
echo « geekologue:$PASSWORD » | chpasswd && \
mkdir /data/lotfi && \
chown geekologue:geekologue /data/lotfi

#Le conteneur démarre avec l’utilisateur geekologue (par défaut, il démarre en root)
USER geekologue

#Le conteneur démarre dans le fichier ~./data
WORKDIR /data


Build de l’image :

#Build d'une image personnalisée basée sur le dockerfile.
#-t pour : tagué l'image avec le nom jcg.
#Le point à la fin pour :  lui indiquer l'emplacement du contexte du build (ou se trouve le dockerfile).
#jcg c'est nom de l'image et 1.0 c'est la version.
docker build -t jcg:1.0 .

Une fois notre image build, nous allons lancer le conteneur à partir de l’image que nous venons de créer.

#-e pour définir la variable d’environnement (PASSWORD) que nous avons déclarer dans le dockerfile
docker run -d –name jcg -e PASSWORD=Pa$$w0rd jcg:1.0

Gestion des images (Image Management) :

Docker build :

  • Lors du build de l’image, chaque instruction qui modifie l’état de l’image (comme RUN ou COPY), Docker crée un conteneur intermédiaire à partir de l’image actuelle, exécute l’instruction dans ce conteneur, puis sauvegarde l’état résultant comme une nouvelle couche d’image. Après avoir exécuté l’instruction, ce conteneur intermédiaire n’est plus nécessaire et peut être supprimé, d’ou l’intérêt du –rm.
  • La commande docker buildcrée des images à partir d’un dockerfile et un « contexte », le contexte c’est le répertoire dans lequel se trouve le Dockerfile, ainsi que de tous ses sous-dossiers. Le contexte peut être spécifié à l’aide d’un chemin local ou d’une URL. Cela implique que Docker examinera cet emplacement ou cette URL pour localiser tous les fichiers et répertoires requis lors de la construction de l’image.

Exemple :

Création (build) depuis un PATH :
Création (build) depuis une URL :

docker build github.com/creack/docker-firefox

Build with – (La création d’une image depuis STDIN) :

Cette technique nous permet de créer une image depuis le stdin, par exemple : cat Dockerfile | docker build - , ce qui fait que docker créer une image sans contexte.

Attention :

    • Les commandes dans le Dockerfile qui nécessitent un contexte, comme COPY, ne peuvent pas copier des fichiers locaux car il n’y a pas de contexte.
    • La commande ADD dans le Dockerfile ne fonctionnera que si elle référence une URL distante, car aucun fichier local n’est disponible

#Ici, le contenu du Dockerfile est passé directement à docker build via STDIN. 
docker build - < Dockerfile

#Dans cet exemple, context.tar.gz est un fichier tarball compressé contenant à la fois le Dockerfile et les fichiers nécessaires au build. 
docker build - < context.tar.gz 
L’utilisation du fichier .dockerignore :

Lien pour de la documentation concernant la création du fichier .dockerignore : https://docs.docker.com/engine/reference/builder/#dockerignore-file
Ce fichier est similaire à un fichier .gitignore dans un dépôt Git ; il est utilisé pour exclure des fichiers et des dossiers du contexte de build envoyé au daemon Docker.

L’utilité de fichier est d’empêcher des fichiers sensibles ou inutiles d’être inclus et potentiellement déployés dans des environnements de production.

 

Syntaxe de la commande build :

  • La commande docker build possède plusieurs options qui permettent de personnaliser le processus de construction de l’image Docker :

# Permet de nommer et éventuellement de taguer l’image.
docker build -t <image-name> .
#Permet de passer des arguments de construction qui peuvent être utilisés dans le Dockerfile
docker build –build-arg VERSION=1.2.3 .
#Spécifie le nom du Dockerfile à utiliser. Utile si le Dockerfile n’a pas le nom par défaut
docker build -f Dockerfile.dev .# Ignore le cache lors de la construction de l’image. Cela garantit que toutes les étapes du Dockerfile sont exécutées de nouveau.
docker build –no-cache .
#Supprime les conteneurs intermédiaires après une construction réussie.
docker build –rm .
#Fusionne toutes les couches de l’image en une seule(Réduit la taille de l’image finale en fusionnant toutes les couches). Attention ça rend plus compliqué le débogage.
docker build –squash .
#Permet de spécifier le mode réseau à utiliser pendant la construction de l’image.
docker build –network=host .
#Ajoute une entrée personnalisée au fichier /etc/hosts du conteneur de build. Lors du test ça n’a pas fonctionner pour moi, pourtant elle est dans la doc officiel.
docker build –add-host=example.com:192.168.1.5 .
#Spécifie la plateforme pour laquelle l’image est construite, utile pour les architectures multi-plateformes.
docker build –platform=linux/amd64 .
#Permet à Docker de transférer les clés SSH pendant le build pour accéder à des ressources privées.
docker build –ssh default .
#Ajoute des métadonnées à l’image sous forme de labels.
docker build –label « version=1.0 » .
#Ajuste les options de sécurité pour la construction.
docker build –security-opt seccomp=unconfined .
#Toujours tenter de mettre à jour l’image pour le FROM. Assure que vous utilisez la version la plus récente de l’image de base.
docker build –pull .
#Spécifie une étape de construction cible dans le Dockerfile.
docker build –target builder . #Construit jusqu’à l’étape nommée ‘builder’ (utile pour les débogages).
#Définit le type d’isolation technologique à utiliser.
docker build –isolation hyperv . #Utilise Hyper-V sur Windows.
#Limite la mémoire disponible pour la construction.
docker build –memory 2g .
#Limite la mémoire swap disponible pour la construction.
docker build –memory-swap 1g .
#Écrit l’ID de l’image construite dans un fichier.
docker build –iidfile /path/to/idfile . #Enregistre l’ID de l’image dans idfile
# Force la suppression des conteneurs intermédiaires même après une construction infructueuse. Nettoie tous les conteneurs temporaires, réussite ou échec.
docker build –force-rm .
# Désactive la vérification de la confiance du contenu. Il créer des images même si la signature n’est pas valide.
docker build –disable-content-trust .
#Compresse le contexte de construction envoyé au démon Docker, utile sur des réseaux lents.
docker build –compress .
#Définit un groupe de contrôle parent pour tous les conteneurs de la construction.
docker build –cgroup-parent mongroupe .
#Utilise une image comme source de cache.
docker build –cache-from monimage:latest . #Utilise monimage:latest pour le cache
#Supprime la sortie verbale de la construction, ne montre pas la sortie détaillée.
docker build –quiet .
#Définit les ulimits pour les conteneurs de construction.
docker build –ulimit nofile=1024:1024 .

Cas pratiques

Plusieurs dockerfile sous des noms différents, dans le contexte :

Nous avons besoin de deux images, avec deux versions debian différente, la 11 et la 12 :

Nous partons du principe que nous avons déjà créer nos dockerfiles, sous le nom (jcg_df_debian11 et jcg_df_debian12) et qu’ils sont dans le même dossier :

#L'image s'appelera jcg_img_deb11 et aura comme version 1.0, elle sera build en se basant sur le fichier (dockerfile) jcg_df_debian11
docker build -f jcg_df_debian11 -t jcg_img_deb11:1.0 .
#L'image s'appelera jcg_img_deb12 et aura comme version 1.0, elle sera build en se basant sur le fichier (dockerfile) jcg_df_debian12 
docker build -f jcg_df_debian12 -t jcg_img_deb12:1.0 .

Attention, par défaut, le fichier Dockerfile est nommé « dockerfile ». Si vous avez un seul fichier portant ce nom,et que vous exécutez la commande dans le même path ou se trouve votre fichier dockerfile, vous n’êtes pas obligé de fournir le paramètre « -f » lors de la commande.


Build d’une image avec une version NODE.js spécifique  :

Supposons que nous ayons une application (ma-web-app) qui ne soit compatible qu’avec la version 16.0 de Node.js, et que nous disposions d’un Dockerfile contenant entre autres la déclaration suivante : ARG NODE_VERSION=14.
Si nous créons un conteneur en utilisant ce Dockerfile, le conteneur sera alors configuré avec Node.js en version 14.

Pour résoudre ce problème sans avoir à modifier directement le Dockerfile, nous utiliserons le paramètre « –build-arg » pour ajuster la valeur de l’argument « ARG ».

#Création de l'image, sans utiliser le cache, en changeant l'argument du build, et en définissant ma-web-app comme tag et 1.6 comme version
docker build --no-cache --build-arg NODE_VERSION=16.0 -t ma-web-app:1.6 .


Build d’une image en mode Hybrid (Contexte local – Dockerfile sur internet) :

Je veux dire par le mode Hybrid : build d’une image avec un contexte local et un dockerfile héberger sur internet par exemple :


#Cette commande va d'abord récupérer un dockerfile, qu'elle placera en sortie STDIN
#Ensuite, cette récupérer par docker build via un pipeline.
curl exemple.com/remote/Dockerfile | docker build -f - .

Différents cas de contexte de build :


#Build à partir d'un docker file dans un path différent de celui du contexte
docker build -f /home/geekologue/dockerfiles/app1/debug /home/geekologue/contextes/app1/

#Build à partir d'un docker file depuis internet et un contexte locale dans un path précis 
curl exemple.com/remote/Dockerfile | docker build -f /home/geekologue/contextes/app1/

Docker Volume :

Trois types de montage qui existent pour docker :

  • Volume :
    • C’est un montage de volume, indépendant de la structure du système de fichier de la machine hôte.
    • Peut être utilisé sur différents systèmes d’exploitations.
  • Bind :
    • Repose sur un chemin spécifique dans la machine hôte.
    • Il est lié directement a la structure du système de fichier (peut causé des incompatibilités avec certains OS).
  • Tmpfs :
    • Stockage temporaire au niveau de la RAM.
    • Rapide, mais ne persiste pas les données entre le redémarrage des conteneurs.

Il existe plusieurs méthode pour interagir avec les volumes, nous allons voir quelque une :

Création d’un volume nommé :

docker volume create –name monVolume

Définition d’options de pilote :

docker volume create  –driver local –opt type=nfs –opt o=addr=192.168.1.10,rw –opt device=:/path/to/dir monNFSVolume

  • --driver local  le volume utilise le pilote de stockage local par défaut de Docker.
  • --opt type=nfs indique que le volume utilisera le système de fichiers en réseau NFS (Network File System).
  • --opt o=addr=192.168.1.10,rw Définition de l’adresse ip du serveur et du type de montage (read/write).
  • --opt device=:/path/to/dir C’est le chemin du dossier (sur le serveur) que l’on souhaite monter sur notre conteneur.

En résumé, cette commande crée un volume Docker nommé monNFSVolume qui monte un dossier (/path/to/dir) d’un serveur NFS (situé à l’adresse 192.168.1.10) en utilisant le pilote de volume local. Ce volume est accessible en lecture et écriture, permettant ainsi aux conteneurs qui l’utilisent de lire et de modifier les données stockées sur ce volume NFS.
En résumé, le pilote local est utilisé pour créer et gérer le volume, mais les options type=nfs et les suivantes indiquent que le contenu réel du volume sera stocké sur un serveur NFS distant, et non localement sur le système de fichiers de l’hôte Docker.

Ajout de labels :

docker volume create –name monOrganizedVolume –label « projet=monProjet » –label « environnement=dev »

 

Les options de volume create :

–availability  #Définit la disponibilité du volume dans un cluster Swarm (active, pause, drain).
#Exemple : docker volume create –name monVolume –availability active

–driver    #Spécifie le pilote de volume à utilise (peut s’écrire -d) (local, nfs, Ceph, rexray/ebs, azure-disk, gcp-disk, rexray/dobs…)
#Exemple : docker volume create –driver nfs –opt o=addr=192.168.10.150,rw monNFS

–group #Définit le groupe de volumes dans un cluster Swarm
#Exemple : docker volume create –driver nfs –name monVolumeNFS

–label   #Ajoute des métadonnées sous forme de labels au volume.
#Exemple : docker volume create –name monVolume –label projet=Web2023

–limit-bytes #Définit la taille minimale du volume en octets
#Exemple : docker volume create –name monVolume –limit-bytes 5000000

–name #Spécifie le nom du volume
#Exemple : docker volume create –name monVolume

–opt  #Définit des options spécifiques au pilote de volume. (peut s’écrire -o)
#Exemple : docker volume create –driver local –opt type=nfs –name monVolumeNFS

–required-bytes  #Définit la taille maximale du volume en octets
#Exemple : docker volume create –name monVolume –required-bytes 10000000

–scope #Définit la portée d’accès au volume
#Exemple : docker volume create –name monVolume –scope single
#Exemple : docker volume create –name monVolume –scope multi

–secret #Gère les secrets associés au volume
#Exemple : docker volume create –name monVolume –secret monSecret

–sharing #Définit le niveau de partage du volume (none, readonly, onewriter, all)
#Exemple : docker volume create –name monVolume –sharing readonly

–topology-preferred #Indique une topologie préférée pour le volume.
#Exemple : docker volume create –name monVolume –topology-preferred maTopologie

–topology-required #Définit une topologie nécessaire pour accéder au volume.
#Exemple : docker volume create –name monVolume –topology-required maTopologie

–type #Spécifie le type d’accès au volume (mount, block).
#Exemple : docker volume create –name monVolume –type mount

Gestion des conteneurs :

Docker run :

  • docker run –mount
    • Montage en mode volume :

Avec le type volume, docker prendra le contenu du volume depuis le host et le monte sur le conteneur dans le dossier /data
Host maître -> Conteneur esclave.

#Ici, myvolume est le nom du volume Docker qui sera monté dans le conteneur au chemin /data.
docker run --mount type=volume,source=volume1,target=/data/ image:version

 

    • Montage en mode bind :

Avec le type bind, docker prendra le contenu du dossier disponible dans le conteneur et le monte dans le dossier de la machine host /data
Host esclave -> Conteneur maître.

#Ici, myvolume est le nom du volume Docker qui sera monté dans le conteneur au chemin /data.
docker run --mount type=bind,source=/home/user/docker/volume1/,target=/data/ image:version

Mémo technique :
Utilisation de -v ou –volume :
Si on utilise le nom d’un volume existant alors le dossier sera monté en mode volume.
Si on utilise le path d’un dossier, alors le dossier sera monté en mode bind.
Utilisation de –mount :
On aura le choix entre les trois types de montage (volume, mount, tmpfs), qu’il faut déclarer explicitement.

Exemple explicite :
docker run -dti –name app1 -v app1:/etc/ debian     #le contenu du conteneur sera « copier » dans le hôte
docker run -dti –name app1 -v /home/baibao/docker/volume/app3:/home/ debian  #Le contenu du hôte sera copier dans le conteneur.