Guide d'Installation et d'Utilisation de Docker sur Ubuntu

Publié le : 09/01/24
Modifié le : 04/06/24 à 10h54

emoji_objects

Documentation officielle : link

Installation


1. Mise à jour du système

Je commence par mettre à jour la liste des paquets.

                            
                                sudo apt update
                            
                            
content_copy

2. Installation des dépendances nécessaires

Installation des paquets qui permettent à apt d'utiliser des paquets sur HTTPS :

                            
                                sudo apt install apt-transport-https ca-certificates curl software-properties-common
                            
                            
content_copy
emoji_objects

- apt-transport-https : Permet à apt de transférer des données via HTTPS.
- ca-certificates : Permet à la machine de vérifier la sécurité des certificats SSL.
- curl : Outil pour transférer des données depuis ou vers un serveur.
- software-properties-common : Ajoute des scripts pour la gestion des logiciels.

3. Ajout de la clé GPG pour le dépôt officiel de Docker

Ajout de la clé GPG officielle de Docker pour m'assurer que les téléchargements sont valides :

                            
                                curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
                            
                            
content_copy
emoji_objects

La clé GPG (GNU Privacy Guard) est un outil de sécurité utilisé pour vérifier l'authenticité et l'intégrité des données téléchargées, dans ce cas, des paquets de Docker.

4. Ajout du dépôt Docker aux sources APT

Ajout du dépôt Docker aux sources apt pour obtenir les dernières versions de Docker :

                            
                                sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
                            
                            
content_copy
emoji_objects

$(lsb_release -cs) : Récupère le nom de la version Ubuntu pour télécharger la version appropriée de Docker.

5. Mise à jour des paquets après l'ajout du dépôt Docker

Après avoir ajouté le dépôt, je mets à jour la liste des paquets :

                            
                                sudo apt update
                            
                            
content_copy

6. Installation de Docker CE (Community Edition)

Maintenant, je peux installer Docker CE :

                            
                                sudo apt install docker-ce
                            
                            
content_copy

7. Vérification de l'installation de Docker

Je vérifie que Docker est bien installé et fonctionne :

                            
                                sudo systemctl status docker
                            
                            
content_copy

Si le service est dead on le start :

                            
                                sudo systemctl start docker
                            
                            
content_copy
sudo systemctl status docker

8. Exécution de Docker sans sudo (Optionnel)

Par défaut, on dois utiliser sudo pour exécuter les commandes Docker. Pour l'éviter, je peux ajouter mon utilisateur au groupe Docker :

                            
                                sudo usermod -aG docker ${USER}
                            
                            
content_copy
emoji_objects

- ${USER} : Variable d'environnement représentant mon nom d'utilisateur. Je remplace ${USER} par mon nom d'utilisateur.
- Je dois me déconnecter et me reconnecter pour que cette modification prenne effet.

9. Test de Docker

Si le conteneur hello-world n'est pas déjà présent sur le système, Docker va automatiquement le télécharger depuis le Docker Hub, qui est un registre public de conteneurs.

                            
                                docker run hello-world
                            
                            
content_copy
emoji_objects

- Téléchargement et exécution automatiques : Si le conteneur hello-world n'est pas trouvé localement, Docker le télécharge automatiquement depuis le Docker Hub et l'exécute.
- Lorsque le téléchargement est terminé, Docker crée un conteneur à partir de cette image et l'exécute.

                            
                            docker run hello-world

                                Hello from Docker!
                                This message shows that your installation appears to be working correctly.
                            
                            

Commandes Docker Courantes


Démarrer/Arrêter Docker

Pour démarrer les services Docker :

                            
                            sudo systemctl start docker
                            
                            
content_copy

Pour arrêter les services Docker :

                            
                            sudo systemctl stop docker
                            
                            
content_copy

Liste de toutes les images Docker disponibles

                            
                            docker images
                            
                            
content_copy

Rechercher une image :

                            
                            docker search <nom_image>
                            
                            
content_copy

Liste des conteneurs actifs

                            
                            docker ps
                            
                            
content_copy

Liste de tous les conteneurs, y compris les inactifs

                            
                            docker ps -a
                            
                            
content_copy

Suppression d'une image Docker

                            
                            docker rmi [nom_image]
                            
                            
content_copy

Suppression d'un conteneur Docker

                            
                            docker rm [id_conteneur]
                            // OU
                            docker rm [nom_conteneur]
                            
                            

Création d'un conteneur

Création en mode interactif

                            
                            docker run -it --name [nom_conteneur]  alpine
                            
                            
content_copy

Création en mode détaché

                            
                            docker run -d --name [nom_conteneur]  alpine
                            
                            
content_copy

Docker Attach

L'utilisation de la commande docker attach permet de ce connecter à un terminal interactif à l'intérieur d'un conteneur Docker en cours d'exécution.

                            
                            docker start conteneur_app
                            
                            
content_copy

                            
                            docker attach conteneur_app
                            
                            
content_copy

Une fois attaché au conteneur, on peut interagir avec lui comme si nous étions directement connecté à un terminal sur la machine hôte.

emoji_objects

Détachement du conteneur : Pour quitter le terminal du conteneur tout en laissant le conteneur s'exécuter, on utilise la combinaison de touches Ctrl + P suivi de Ctrl + Q. Cela me détachera du terminal du conteneur sans l'arrêter.

Exec

La commande docker exec est utilisée pour exécuter une commande à l'intérieur d'un conteneur Docker en cours d'exécution. Sans me connecter au conteneur.
Exemple : Création d'un fichier .txt dans un conteneur en cours d'exécution sans se connecter.

                            
                                toto@srv:~$ docker start conteneur_d_alpine
                                toto@srv:~$ docker exec conteneur_d_alpine touch /tmp/toto.txt
                                toto@srv:~$ docker exec -it conteneur_d_alpine sh
                                / # cd tmp
                                /tmp # ls
                                toto.txt
                            
                            

Exemple : Se connecter au terminal d'un conteneur en cours d'exécution.

                            
                                docker start conteneur_d_alpine
                            
                            
content_copy

Création d'un réseau

Les réseaux Docker permettent aux conteneurs de communiquer entre eux de manière isolée et efficace.
Création un réseau :

                            
                            docker network create mon_reseau
                            
                            
content_copy

Supprimer un réseau :

                            
                            docker network rm <mon_reseau>
                            
                            
content_copy

Supprimer tous les réseaux à l'excetion des réseaux par défaut :

                            
                            docker network prune
                            
                            
content_copy

Logs en temps réel d'un service

                            
                            docker logs -f [nom_conteneur] OU [id_conteneur]
                            
                            
content_copy

Docker compose logs

La commande docker compose logs est un outil puissant pour consulter et suivre les logs de tous les services définis dans un fichier docker-compose.yml. Elle est particulièrement utile dans des environnements de développement et de test où plusieurs conteneurs sont lancés via Docker Compose, et on souhaites avoir une vue consolidée des sorties de logs de ces services.
Usage Bsique : docker compose logs [options] [SERVICE...]

                            
                            docker compose logs [options] [SERVICE...]
                            docker compose logs -f mon_service_1
                            
                            
emoji_objects

- [options] : Plusieurs options peuvent être utilisées avec docker-compose logs pour personnaliser son comportement.
- Options Communes :
   -f, --follow : Suit les logs en temps réel.
   --no-color : Supprime la coloration des logs, utile pour des terminaux ne supportant pas les couleurs ou pour des redirections de sortie.
   -t, --timestamps : Ajoute des horodatages à chaque entrée de log, ce qui peut être utile pour le débogage et le suivi temporel des événements.
   --tail="N" : Affiche les dernières N lignes de logs pour chaque service, où N peut être un nombre ou all pour tout afficher.

Exemples d'Utilisation :

> Suivre en temps réel les logs de tous les services définis dans docker-compose.yml :

                            
                            docker-compose logs -f
                            
                            
content_copy

> Suivre les logs de services spécifiques avec des horodatages :

                            
                            docker-compose logs -f -t mon_service_1 mon_service_2
                            
                            
content_copy

> Afficher les 100 dernières lignes de logs pour un service spécifique :

                            
                            docker-compose logs --tail=100 mon_service
                            
                            
content_copy

Utilisation de docker compose build

La commande docker compose build est utilisée pour construire les images Docker spécifiées dans un fichier docker-compose.yml.

                            
                            toto@srv:~/docker$ docker compose build
                            [+] Building 1.2s (40/40) FINISHED
                            
                            
emoji_objects

- L'utilisation de : docker compose ou docker-compose est identique.
- La commande docker compose build peut être utilisée pour construire des images individuelles ou des groupes d'images spécifiques en spécifiant les noms des images ou des groupes d'images dans la commande.

Exemple : Utilisation de docker compose build pour construire des images individuelles et un groupe d'images spécifiques.

                            
                            toto@srv:~/docker$ docker compose -f docker-compose.yml build web
                            // Ou un groupe d'images
                            toto@srv:~/docker$ docker compose -f docker-compose.yml build web db
                            
                            

Arrêter un conteneur

                            
                            docker stop <nom_du_conteneur>
                            
                            
content_copy

                            
                            docker stop <id_conteneur>
                            
                            
content_copy

Arrêt et suppression de tous les conteneurs d'un docker-compose

La commande docker compose down est utilisée pour arrêter et supprimer tous les conteneurs, réseaux et volumes associés à un service ou à un ensemble de services spécifiés dans un fichier docker-compose.yml.
Cette commande permet de nettoyer l'environnement Docker en arrêtant proprement les conteneurs et en supprimant les ressources Docker associées à notre application.

                            
                            toto@srv:~/projet-rt0707/docker$ docker compose down
                            [+] Running 7/7
                             ✔ Container container_1     Removed       0.0s
                             ✔ Container container_2     Removed       12.9s
                             ✔ Container container_3     Removed       12.9s
                            
                            
emoji_objects

- L'utilisation de docker compose down, ne supprime pas les images utilisés dans le docker-compose.
- Par conséquent, si des modifications sont apportées aux Dockerfiles, il est nécessaire d'exécuter la commande docker compose build pour reconstruire les images Docker à partir des Dockerfiles mis à jour.

Création d'un conteneur Alpine en ligne de commandes


1. Recherche de l'Image Alpine

D'abord, je vérifie si l'image Alpine est disponible sur Docker Hub. Je peux le faire avec la commande suivante :

                            
                                docker search alpine
                            
                            
content_copy
                            
                                toto@srv:~$ docker search alpine
                                NAME                               DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
                                alpine                             A minimal Docker image based on Alpine Linux…   10587     [OK]
                                alpinelinux/docker-cli             Simple and lightweight Alpine Linux image wi…   10
                                alpinelinux/alpine-gitlab-ci       Build Alpine Linux packages with Gitlab CI      3
                                alpinelinux/gitlab-runner-helper   Helper image container gitlab-runner-helper …   6       
                            
                            
emoji_objects

- Cette commande me montrera les images disponibles liées à Alpine Linux.
- STARS : Cette colonne indique le nombre d'étoiles que les utilisateurs de la communauté Docker ont attribuées à l'image.
- OFFICIAL : Cette colonne indique si l'image est une image Docker officielle ou non.
- AUTOMATED : Cette colonne indique si la construction et la mise à jour de l'image sont automatisées, souvent via un processus de CI/CD.

2. Téléchargement de l'Image Alpine

Ensuite, je télécharge l'image officielle d'Alpine Linux :

                            
                                docker pull alpine
                            
                            
content_copy
emoji_objects

- Cette commande va télécharger la dernière version de l'image Alpine depuis Docker Hub.

Après le téléchargement, je vérifie si l'image est bien présente sur mon système :

                            
                                toto@srv:~$ docker images
                                REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
                                alpine       latest    f8c20f8bbcb6   4 weeks ago   7.38MB
                            
                            

3. Comprendre les Modes Interactif et Détaché dans Docker

Docker offre deux modes principaux pour exécuter des conteneurs : le mode interactif (-it) et le mode détaché (-d) (ou le mode démon). Chacun a ses propres caractéristiques et cas d'utilisation.

  • Mode Interactif (-it)

Commande de base : docker run -it --name [name] [image] [command]
Utilisation : Pour lancer un conteneur avec lequel je peux interagir directement.
Fonctionnement : Ouvre un terminal à l'intérieur du conteneur et me permet d'exécuter des commandes en temps réel.
Cas d'utilisation :

  • Développement et test d'applications.
  • Exploration et débogage de conteneurs.
Exemple :

                            
                                docker run -it --name conteneur_it_alpine alpine [command]
                            
                            
emoji_objects

- [command] : Si aucune commande n'est spécifiée après le nom de l'image (alpine), Docker exécutera la commande par défaut définie dans l'image, qui est /bin/sh pour Alpine.

Avantages du Mode Interactif

Interaction Directe : Idéal pour voir en direct ce qui se passe dans le conteneur.
Débogage Facile : Permet de résoudre les problèmes rapidement.

Inconvénients du Mode Interactif

Non Autonome : Le conteneur s'arrête quand on quittes le terminal.
Moins adapté pour la production : Peut nécessiter une surveillance constante.

  • Mode Détaché (-d)

Commande de base : docker run -d --name [name] [image] [command]
Utilisation : Pour lancer un conteneur qui s'exécute en arrière-plan, sans interaction directe.
Fonctionnement : Le conteneur démarre et continue de tourner jusqu'à ce qu'il soit explicitement arrêté. *
Cas d'utilisation :

  • Exécution de serveurs web, bases de données, et autres services en continu.
  • Applications en production.
Exemple :

                            
                                docker run -d --name conteneur_d_alpine alpine [command]
                            
                            
content_copy
emoji_objects

- [command] : Même observation que pour le mode (-it).
- * : Un conteneur Docker lancé en mode détaché avec une commande rapide (comme /bin/sh) s'arrêtera immédiatement si aucune tâche continue n'est définie.

Avantages du Mode Détaché

Indépendance : Le conteneur continue de fonctionner même après fermeture du terminal.
Adapté à la production : Convient aux services devant rester actifs longtemps.

Inconvénients du Mode Détaché

Moins d'Interactivité : Pas idéal pour les tâches nécessitant des retours en temps réel.
Débogage moins immédiat : Peut être plus difficile de diagnostiquer des problèmes.

4. Créer un Conteneur Docker en Mode Interactif

Maintenant que j'ai une meilleure compréhension des différents modes qu'offre Docker, je peux créer les deux types de conteneurs.

Création d'un Conteneur Alpine en Mode Interactif

Objectif : Lancer un conteneur Docker en mode interactif pour pouvoir exécuter des commandes directement.

                            
                                toto@srv:~$ docker run -it --name conteneur_it_alpine alpine
                                / # ls
                                bin    dev    etc    home   lib    media  mnt    opt    .  .  .
                            
                            
emoji_objects

- Une fois le conteneur lancé, je suis automatiquement dans le shell interactif de l'image Alpine.
- exit : Pour quitter et arrêter le conteneur.

Une fois que j'ai quitté le conteneur en utilisant la commande exit, je peux saisir la commande docker ps -a pour voir la liste de mes conteneurs et leur état.

                            
                                toto@srv:~$ docker ps -a
                                CONTAINER ID   IMAGE     COMMAND     CREATED         STATUS                     PORTS     NAMES
                                dbe64a1899e7   alpine    "/bin/sh"   4 minutes ago   Exited (0) 4 seconds ago             conteneur_it_alpine
                            
                            
emoji_objects

- COMMAND : "/bin/sh" Correspond à la commande par défaut présente dans l'image Alpine.
- STATUS : Exited Indique que le conteneur est arrêté.
- PORT : Indique les ports réseau exposés par le conteneur et mappés sur le système hôte.

Relancer le conteneur :

                            
                                toto@srv:~$ docker start conteneur_it_alpine
                                toto@srv:~$ docker exec -it conteneur_it_alpine /bin/sh
                                / #
                            
                            

5. Création d'un Conteneur Alpine en Mode Détaché (Démon)

Objectif : Lancer un conteneur Docker qui continue de s'exécuter en arrière-plan.

emoji_objects

- Comme indiqué précédemment, en mode détaché, l'objectif est de démarrer un service autonome qui continue de fonctionner indépendamment.
- Pour refléter ce comportement, je vais simuler le service en utilisant la commande tail -f /dev/null, qui ne se termine pas.

Cet exemple crée un conteneur en mode détaché sans aucun service, il s'arrête immédiatement.

                            
                                toto@srv:~$ docker run -d --name conteneur_d_alpine alpine
                                4de539d01765595e22732da9cc46635b770fae2bbe879206c75dbf9e2a12b1c0
                                toto@srv:~$ docker ps -a
                                CONTAINER ID   IMAGE     COMMAND     CREATED          STATUS                      PORTS     NAMES
                                4de539d01765   alpine    "/bin/sh"   11 seconds ago   Exited (0) 10 seconds ago             conteneur_d_alpine
                            
                            

Maintenant, je vais créer un conteneur en mode détaché avec un service qui s'exécute en continu afin de maintenir le conteneur actif.

                            
                                toto@srv:~$ docker run -d --name conteneur_d_s_alpine alpine tail -f /dev/null
                                dd7b2ae1e5da928a9e4e165cc5312a815ffd4c9c4affa437e471edfd7ac6bcc3
                                toto@srv:~$ docker ps
                                CONTAINER ID   IMAGE     COMMAND               CREATED          STATUS          PORTS     NAMES
                                dd7b2ae1e5da   alpine    "tail -f /dev/null"   5 minutes ago    Up 5 minutes              conteneur_d_s_alpine
                                dbe64a1899e7   alpine    "/bin/sh"             37 minutes ago   Up 26 minutes             conteneur_it_alpine       
                            
                            
emoji_objects

- On peut remarquer que dans le champ COMMAND, nous n'avons plus /bin/sh, mais tail -f /dev/null.
- On remarque également que dans le champ STATUS, le conteneur est toujours actif, affichant Up 5 minutes.

Pour basculer en mode interactif avec ce conteneur de base qui est en mode détaché, je peux accomplir cette action en exécutant la commande suivante :

                            
                                toto@srv:~$ docker exec -it conteneur_d_s_alpine /bin/sh
                                / # 
                            
                            
emoji_objects

- On accède au terminal d'un conteneur en mode détaché uniquement en cas de nécessité, comme pour le débogage ou des ajustements spécifiques.
- Cette approche minimise les interruptions du service du conteneur et maintient la stabilité de l'environnement de production ou de test.

Création d'un conteneur Alpine Avec Dockerfile et Docker-Compose


1. Qu'est-ce qu'un Dockerfile ?

Un Dockerfile est un fichier texte qui contient une série d'instructions pour construire une image Docker. Il n'est pas nécessaire de l'installer séparément car il fait partie intégrante de Docker.

emoji_objects

- Un Dockerfile est un script composé de diverses commandes que Docker exécute pour construire automatiquement une image personnalisée.
- Il permet de définir l'environnement de l'application, y compris le système d'exploitation, les langages de programmation, les configurations de l'environnement, les fichiers à ajouter, etc.

Structure de Base d'un Dockerfile

  • FROM: Définit l'image de base. Exemple: FROM ubuntu:18.04
  • LABEL: Ajoute des métadonnées à l'image. Exemple: LABEL maintainer="nom@example.com"
  • RUN: Exécute des commandes dans le conteneur. Exemple: RUN apt-get update && apt-get install -y python3
  • COPY: Copie des fichiers et dossiers du système hôte vers l'image. Exemple: COPY . /app
  • ADD: Similaire à COPY, mais peut décompresser des fichiers compressés et télécharger depuis des URLs. Exemple: ADD http://example.com/big.tar.xz /usr/src/things/
  • CMD: Fournit la commande à exécuter lors du lancement du conteneur. Exemple: CMD ["python3", "./app.py"]
  • ENTRYPOINT: Configure un conteneur qui s'exécute comme un exécutable. Exemple: ENTRYPOINT ["python3"]
  • ENV: Définit des variables d'environnement. Exemple: ENV APP_HOME /app
  • EXPOSE: Informe Docker que le conteneur écoute sur des ports spécifiques. Exemple: EXPOSE 80
  • VOLUME: Crée un point de montage pour accéder et stocker des données persistantes. Exemple: VOLUME /data
  • WORKDIR: Définit le répertoire de travail. Exemple: WORKDIR /app
Exemple de Dockerfile qui illustre certaines des directives les plus couramment utilisées

                                
                                # Utilise une image de base. Ici, Ubuntu est utilisé comme exemple.
                                FROM ubuntu:20.04
                                    
                                # Définit le mainteneur du fichier Dockerfile.
                                LABEL maintainer="nom@example.com"
                                    
                                # Définit des variables d'environnement qui seront utilisées dans le Dockerfile.
                                ENV APP_HOME=/app \
                                    PORT=8080
                                    
                                # RUN exécute des commandes dans un nouveau layer au-dessus de l'image courante.
                                # Utile pour installer des logiciels, des bibliothèques, etc.
                                RUN apt-get update && apt-get install -y \
                                    curl \
                                    nginx \
                                    && rm -rf /var/lib/apt/lists/*
                                    
                                # COPY copie des fichiers ou dossiers de ton système de fichiers local dans le filesystem du container.
                                COPY ./start.sh /usr/local/bin/start.sh
                                    
                                # ADD est similaire à COPY, mais peut aussi décompresser des archives et télécharger depuis des URLs.
                                ADD https://example.com/big.tar.gz /tmp/big.tar.gz
                                    
                                # Définit le répertoire de travail pour les instructions qui suivent.
                                WORKDIR $APP_HOME
                                    
                                # CMD fournit une commande par défaut pour exécuter le conteneur.
                                CMD ["nginx", "-g", "daemon off;"]
                                    
                                # Expose un port pour permettre au container de communiquer avec l'extérieur.
                                EXPOSE $PORT
                                    
                                # VOLUME crée un point de montage pour lier ou monter un fichier ou un répertoire.
                                VOLUME [ "/data" ]
                                    
                                # USER définit l'utilisateur (UID) qui exécutera le conteneur.
                                USER 1000
                                    
                                # HEALTHCHECK permet de vérifier l'état de santé de l'application dans le conteneur.
                                HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
                                    CMD curl -f http://localhost:$PORT/ || exit 1
                                    
                                # ENTRYPOINT permet de configurer le conteneur pour qu'il s'exécute comme un exécutable.
                                ENTRYPOINT ["./start.sh"]
                                    
                                # ARG définit une variable qui peut être passée au Dockerfile au moment du build.
                                ARG VERSION=1.0
                                
                                # STOPSIGNAL envoie un signal spécifique pour arrêter le conteneur.
                                STOPSIGNAL SIGTERM
                                    
                                # SHELL permet de définir le shell par défaut pour les commandes RUN, CMD, etc.
                                SHELL ["/bin/bash", "-c"]                            
                                
                            
Création d'un Dockerfile Simple

Supposons que je veuille créer une image Docker pour une application Python simple.

Je crée un dossier pour mon projet :
                                
                                toto@srv:~$ mkdir mon_app_docker
                                toto@srv:~$ cd mon_app_docker
                                toto@srv:~/mon_app_docker$
                                
                            
Je crée un fichier Dockerfile dans ce dossier :
                                
                                toto@srv:~/mon_app_docker$ touch Dockerfile
                                // J'ouvre le fichier
                                toto@srv:~/mon_app_docker$ vim Dockerfile
                                
                            
J'ouvre le Dockerfile et j'écris les instructions suivantes :
                                
                                # Utilise l'image de base Python 3.8
                                FROM python:3.8-slim
                                    
                                # Définit le répertoire de travail dans le conteneur
                                WORKDIR /app
                                    
                                # Copie le fichier Python nécessaire dans le conteneur
                                # L'idéal est de partager un répertoire entre l'hôte et le conteneur
                                COPY app.py /app
                                    
                                # Commande pour exécuter le script Python
                                CMD ["python", "app.py"]
                                
                            
emoji_objects

- Ici, je suppose que j'ai un fichier app.py dans le même dossier.
- Sur Vim :
  -> Pour passer en mode écriture il faut taper i
  -> Pour sauvegarder on clique sur la touche échap puis :w
  -> Pour quitter :q
  -> On peut faire les deux commandes en une seule fois :wq

2. Construction de l'image Docker à partir d'un Dockerfile

Il faut se positionner au même endroit où se trouve le fichier Dockerfile.

                                
                                toto@srv:~/mon_app_docker$ docker build -t mon_app_python .
                                [+] Building 2.2s (8/8) FINISHED                                    docker:default
                                 => [internal] load build definition from Dockerfile                          0.0s
                                 => => transferring dockerfile: 310B                                          0.0s
                                 => [internal] load .dockerignore                                             0.0s
                                 => => transferring context: 2B                                               0.0s
                                 => [internal] load metadata for docker.io/library/python:3.8-slim            1.8s
                                 => [1/3] FROM docker.io/library/python:3.8-slim@sha256:945015cb3f91d         0.1s
                                 => => resolve docker.io/library/python:3.8-slim@sha256:945015cb3f91d         0.1s
                                 => [internal] load build context                                             0.0s
                                 => => transferring context: 56B                                              0.0s
                                 => CACHED [2/3] WORKDIR /app                                                 0.0s
                                 => [3/3] COPY app.py /app                                                    0.1s
                                 => exporting to image                                                        0.1s
                                 => => exporting layers                                                       0.0s
                                 => => writing image sha256:9fe498205e6d258808af4f00d69d385bdece7242c         0.0s
                                 => => naming to docker.io/library/mon_app_python                             0.0s
                                
                            
emoji_objects

- Le . dans la commande signifie que le Dockerfile se trouve dans le même répertoire.

Pour vérifier si l'image a bien été créée on peut taper docker images.

                                
                                toto@srv:~/mon_app_docker$ docker images
                                REPOSITORY       TAG       IMAGE ID       CREATED         SIZE
                                mon_app_python   latest    c6592e54234e   8 minutes ago   128MB
                                alpine           latest    f8c20f8bbcb6   4 weeks ago     7.38MB
                                hello-world      latest    d2c94e258dcb   8 months ago    13.3kB
                                
                            
Exécuter le Conteneur basé sur cette image :
                                
                                toto@srv:~/mon_app_docker$ docker run --name conteneur_app_dockerfile mon_app_python
                                Hello, World!
                                
                            
emoji_objects

- Pour voir à nouveau "Hello, World!" après une nouvelle exécution, il faut consulter les journaux de log en utilisant la commande docker logs conteneur_app_dockerfile.

3. Bonnes Pratiques pour les Dockerfiles

  • Images de base légères : Choisir des images de base légères comme Alpine pour réduire la taille et augmenter la sécurité de l'image Docker.
  • Regroupement des commandes RUN : Regrouper les commandes RUN pour minimiser le nombre de couches, rendant l'image plus légère et plus propre.
  • Nettoyage du cache : Nettoyer le cache des gestionnaires de paquets après les installations pour réduire la taille de l'image.
  • Préférer COPY à ADD : Utiliser COPY pour copier des fichiers locaux dans l'image, car c'est plus simple et transparent que ADD.
  • Utilisateur non-root : Créer et utiliser un utilisateur avec des privilèges limités pour améliorer la sécurité du conteneur.

4. Qu'est-ce qu'un Docker-Compose ?

emoji_objects

- docker compose --help Pour lister les commandes disponibles.
- Pour connaître la version de Docker-compose : docker compose version

Docker Compose est un outil conçu pour simplifier le processus de définition et de partage de multi-conteneurs Docker. Bien qu'il ne soit pas toujours inclus par défaut dans l'installation standard de Docker, surtout sur certains systèmes Linux comme Ubuntu, les versions récentes de Docker le proposent comme un plugin intégré, rendant son utilisation plus fluide et intégrée.

Pourquoi Docker Compose est-il utile ?
  • Simplicité de Docker : Docker vise à rester simple et léger. Docker Compose, en tant que plugin ou outil séparé, ajoute des fonctionnalités pour les utilisateurs ayant besoin de gérer des configurations de multi-conteneurs sans alourdir l'installation de base pour ceux qui n'en ont pas besoin.
  • Flexibilité : Docker Compose est idéal pour des configurations impliquant plusieurs conteneurs interconnectés. Il permet une définition et un déploiement faciles de services, réseaux et volumes dans une architecture de conteneurs.
Possibilités offert par un docker compose :
                                
                                version: '2'                                        # Spécifie la version de Docker Compose utilisée

                                services:
                                    web:                                            # Nom du service
                                        image: nginx:latest                         # Image Docker à utiliser
                                        build:                                      # Option pour construire l'image
                                            context: ./path/to/build/context        # Contexte de build (répertoire contenant le Dockerfile)
                                            dockerfile: Dockerfile                  # Nom du Dockerfile (facultatif)
                                            args:                                   # Arguments de build
                                                BUILD_ENV: development
                                        command: ["nginx", "-g", "daemon off;"]     # Commande à exécuter dans le conteneur
                                        environment:                                # Variables d'environnement
                                            - NODE_ENV=production
                                        env_file:                                   # Fichier de variables d'environnement
                                            - .env
                                        ports:                                      # Ports à exposer
                                            - "80:80"
                                        volumes:                                    # Volumes pour la persistance des données
                                            - type: bind
                                                source: ./data
                                                target: /data
                                            - my_volume:/volume_data
                                        networks:                                   # Réseaux auxquels le service doit être connecté
                                            - my_network
                                        depends_on:                                 # Spécifie les dépendances de ce service
                                            - database
                                        deploy:                                     # Options de déploiement (utiles pour Docker Swarm)
                                            replicas: 3
                                            update_config:
                                                parallelism: 2
                                                delay: 10s
                                        healthcheck:                                # Configuration du healthcheck
                                            test: ["CMD", "curl", "-f", "http://localhost"]
                                            interval: 1m30s
                                            timeout: 10s
                                            retries: 3
                                            start_period: 40s
                                    
                                    database:                                       # Un autre service
                                        image: postgres:latest
                                        environment:
                                            POSTGRES_PASSWORD: example
                                    
                                    volumes:                                        # Définition des volumes
                                        my_volume:
                                    
                                    networks:                                       # Définition des réseaux
                                        my_network:
                                    
                                # D'autres sections comme 'configs' et 'secrets' peuvent être utilisées pour des cas spécifiques.
                                
                            

Voici un exemple simplicte de a quoi ressemble un Docker-compose :

                                
                                services:
                                    web:
                                        build: .
                                        ports:
                                            - "5000:5000"
                                        volumes:
                                            - .:/code
                                    redis:
                                        image: redis
                                
                            

5. Création d'un conteneur Web Httpd Simple

Réalisation d'un environnement Docker qui exécute un serveur web Httpd et qui partage un volume avec l'hôte.

Étape 1 : Préparation de l'Environnement sur l'Hôte

Création d'un dossier pour le projet.

                                
                                toto@srv:~$ mkdir mon_serveur_httpd
                                toto@srv:~$ cd mon_serveur_httpd
                                toto@srv:~/mon_serveur_httpd$
                                
                            

Création d'un dossier www qui contiendra les fichiers html.

                                
                                toto@srv:~/mon_serveur_httpd$ mkdir www
                                
                            
Étape 2 : Création du Dockerfile

Création du fichier Dockerfile dans le dossier du projet.

                                
                                toto@srv:~/mon_serveur_httpd$ touch Dockerfile
                                
                            

Edition du Dockerfile

                                
                                # Utiliser l'image officielle Apache (httpd)
                                FROM httpd:latest
                                
                                # LABEL permet d'ajouter des métadonnées à une image sous forme de clé-valeur.
                                # LABEL = ...
                                LABEL maintainer="yourname@example.com"

                                # Définir le répertoire de travail dans le conteneur
                                WORKDIR /usr/local/apache2/htdocs/
                                
                            
emoji_objects

- Ce Dockerfile utilise l'image httpd.

Étape 3 : Création du docker-compose.yml

Le fichier docker-compose.yml va définir comment le service doit être exécuté, y compris le mappage des ports et des volumes.

                                
                                touch docker-compose.yml
                                
                            

Edition du fichier

                                
                                version: '2'

                                services:
                                    web:
                                        build: .
                                        container_name: container_httpd_simple
                                        ports:
                                          - "80:80"
                                        volumes:
                                          - ./www:/usr/local/apache2/htdocs/
                                          # On peut également mettre le chemin absolu au lieu de ./www
                                          # Exemple : /home/toto/mon_serveur_httpd/www/:/usr/local/apache2/htdocs/
                                
                            
emoji_objects

- Dans ce fichier, je définis un service web qui va construire l'image à partir du Dockerfile.
- Le port 80 est mappé pour l'accès externe. Le dossier www de l'hôte est monté sur le répertoire de document racine d'Apache dans le conteneur.

Étape 4 : Construire et Démarrer le Service
                                
                                // Si on utilise le plugin docker-compose 
                                docker compose up -d 
                                // Si on utilise une installation de docker-compose
                                docker-compose up -d 
                                
                            
                                
                                toto@srv:~/mon_serveur_httpd$ docker compose up -d
                                [+] Building 5.6s (6/6) FINISHED                              docker:default
                                => [web internal] load build definition from Dockerfile                 0.1s
                                .
                                .
                                ✔ Container container_httpd_simple  Started                             0.2s

                                toto@srv:~/mon_serveur_httpd$ docker ps -a
                                CONTAINER ID   IMAGE                   COMMAND              CREATED         STATUS         PORTS                               NAMES
                                16154f0d9118   mon_serveur_httpd-web   "httpd-foreground"   6 seconds ago   Up 4 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   container_httpd_simple
                                
                            

Actuellement, j'utilise un terminal dans une machine virtuelle distante. Pour accéder à l'affichage de mon fichier index.html, j'ouvre mon navigateur et me connecte à mon adresse IP privée, à savoir http://10.11.2.225/index.html.

Gestion et Inspection d'un Conteneur Docker


1. Récupérer les Paramètres Système du Conteneur

Objectif : Obtenir des informations détaillées sur le conteneur.
Pour ce faire, nous utilisons la commande inspect de Docker.

                                
                                toto@srv:~$ docker start conteneur_it_alpine
                                conteneur_it_alpine
                                toto@srv:~$ docker inspect conteneur_it_alpine
                                
                            
                                
                                [
                                    {
                                        "Id": "dbe64a1899e7d016972ef64f95ca278fa33408ed5c3840ea38965f72e215fd73",
                                        "Created": "2024-01-10T10:16:51.196899174Z",
                                        "Path": "/bin/sh",
                                        "Args": [],
                                        "State": {
                                            "Status": "running",
                                            "Running": true,
                                            "Paused": false,
                                            "Restarting": false,
                                            "OOMKilled": false,
                                            "Dead": false,
                                            .
                                            .
                                        }
                                        .
                                        .
                                    }
                                ]
                                
                            
emoji_objects

- La commande affiche une sortie au format JSON contenant toutes les configurations et états du conteneur.

La commande docker inspect permet de récupérer une grande variété d'informations sur un conteneur. Pour cibler spécifiquement l'état du conteneur, par exemple, on peut utiliser l'option --format.
Exemple :

                                
                                toto@srv:~$ docker inspect --format '{{.State.Status}}' conteneur_it_alpine
                                running
                                
                            
emoji_objects

- Docker utilise le modèle Go pour structurer les informations d'un conteneur.
- On peut cibler des informations précises à récupérer, telles que l'adresse IP du conteneur.

Exemple : Récupérer l'adresse IP du conteneur avec la commande inspect.
Pour cela, il faut comprendre la structure du modèle Go utilisé par Docker :
Il s'agit d'un fichier JSON, donc représenté par des paires clé-valeur. Nous ciblons la clé NetworkSettings, le tableau Networks, puis bridge et enfin la valeur que nous souhaitons récupérer, IPAddress.
Cela sera plus clair avec l'arborescence suivante :

                                
                                toto@srv:~$ docker inspect conteneur_it_alpine
                                [
                                    {
                                        "Id": "dbe64a1899e7d016972ef64f95ca278fa33408ed5c3840ea38965f72e215fd73",
                                        "Created": "2024-01-10T10:16:51.196899174Z",
                                        .
                                        .,
                                        "NetworkSettings": {
                                            "Bridge": "",
                                            .
                                            .
                                            "Networks": {
                                                "bridge": {
                                                    .
                                                    .
                                                    "IPAddress": "172.17.0.2",
                                                    .
                                                    .
                                                }
                                            }
                                        }
                                    }
                                ]
                                
                            

En suivant cette arborescence, la commande pour récupérer l'adresse IP du conteneur serait la suivante :

                                
                                toto@srv:~$ docker inspect --format '{{.NetworkSettings.Networks.bridge.IPAddress}}' conteneur_it_alpine
                                172.17.0.2