<style> .slides { font-size: 3rem; background: url('https://plus.unsplash.com/premium_photo-1661879970066-a8b18d89cb64?q=80&w=3948&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D') center/cover no-repeat; } .slides > section { position: absolute; inset: 0; background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.2); color: white; display: grid; place-content: center; box-sizing: border-box; } .slides > section:first-of-type { font-size: 6rem; } .slides h1, .slides h2, .slides h3, .slides h4, .slides h5, .slides h6, h1, h2, h3, h4, h5, h6 { padding: 1rem; color: #e74c3c; } .slides strong, .slides em { color: #ff9676; } .slides pre code { width: auto; max-height: initial; } .slides code { color: #ffbd96; font-style: italic; } .slides p { padding: 0 2.4rem; } .slides .alert { width: 90%; margin: auto; } .slides ul, .slides ol { width: calc(100% - 4rem); } html, body, .ui-content { color: #ecf0f1; } .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { color: #ecf0f1; border-bottom-color: #ffffff4d; } .markdown-body img { background-color: transparent; } .ui-toc-dropdown { background-color: #2c3e50; } .ui-toc-label.btn { background-color: #192b38; color: #fff; } .ui-toc-dropdown .nav>.active>a, .ui-toc-dropdown .nav>li>a:hover, .ui-toc-dropdown .nav>li>a:focus { color: #fff; border-left: 2px solid #fff; } .expand-toggle:hover, .expand-toggle:focus, .back-to-top:hover, .back-to-top:focus, .go-to-bottom:hover, .go-to-bottom:focus { color: #fff; } .markdown-body blockquote { color: #bcbcbc; } .markdown-body table tr { background-color: #4b5f70; } .markdown-body table tr:nth-child(2n) { background-color: #3e4f5f; } .markdown-body code, .markdown-body tt { color: #f0f0f0; background-color: rgba(230, 230, 230, 0.3); } a, .open-files-container li.selected a { color: #3498db; } </style> # Docker --- # **1. Introduction à Docker** --- ## **Pourquoi Docker ?** **Problématique :** Avant Docker, les développeurs et les ops rencontraient souvent le problème classique : - *"Ça marche sur ma machine, mais pas en production !"* - Les différences d’environnements (OS, librairies, versions) rendaient le déploiement complexe et peu fiable. ---- **Solution : Docker !** Docker permet de : 1. **Isoler** les applications dans des conteneurs. 2. **Standardiser** les environnements de développement, test et production. 3. **Faciliter** le déploiement et la scalabilité. ---- **Exemple concret :** - Vous développez une application Python avec Flask. - Sur votre machine, tout fonctionne. - En production, il manque une dépendance ou la version de Python est différente. - Avec Docker, vous créez un conteneur qui contient tout ce dont votre application a besoin, et il fonctionnera de la même manière partout. --- ## **Conteneurs vs Machines Virtuelles** **Comparaison en Tableau :** | **Aspect** | **Machine Virtuelle (VM)** | **Conteneur Docker** | |---------------------------|-------------------------------------|------------------------------------| | **Système d'exploitation**| OS complet (invité) | Partage le noyau de l’OS hôte | | **Ressources** | Lourd (CPU, RAM, disque) | Léger et rapide | | **Démarrage** | Lent | Rapide | | **Isolation** | Totale | Légère mais suffisante | | **Exemple d'outil** | VirtualBox, VMware | Docker, containerd | --- ![](https://www.netapp.com/media/container-vs-vm-inline1_tcm19-82163.png?v=85344?v=85344 =1200x) --- ## **Concepts de Base** **1. Images Docker :** - Une **image** est un modèle (ou "blueprint") pour créer des conteneurs. - Elle contient tout ce dont une application a besoin pour fonctionner : code, librairies, outils, configurations. - Exemple : `nginx`, `python:3.8`, `mysql`. ---- **2. Conteneurs :** - Un **conteneur** est une instance d’une image en cours d’exécution. - C’est comme une "maison construite" à partir du "blueprint" (l’image). - Exemple : Si vous avez une image `nginx`, vous pouvez lancer plusieurs conteneurs Nginx à partir de cette image. ---- **3. Registres (Registries) :** - Un **registre** est un endroit où sont stockées les images Docker. - Le registre public le plus connu est **Docker Hub** (https://hub.docker.com). - Vous pouvez aussi créer des registres privés pour vos propres images. **Exemple :** - Vous téléchargez une image depuis Docker Hub : ```bash docker pull nginx ``` - Vous lancez un conteneur à partir de cette image : ```bash docker run -d -p 8080:80 --name my-nginx nginx ``` Ici, `my-nginx` est le nom du conteneur, et il écoute sur le port 8080 de votre machine. --- ## **Résumé de l’Introduction** **Docker en 3 points :** 1. **Isolation** : Chaque application tourne dans son propre environnement. 2. **Portabilité** : Une image Docker fonctionne partout (Linux, macOS, Windows). 3. **Efficacité** : Léger et rapide comparé aux machines virtuelles. --- ## **Capture d’écran de Docker Hub** ![CleanShot 2025-01-23 at 19.39.14](https://hackmd.io/_uploads/Hycx6-l_1l.png =x600) --- ## **Exemple de Commandes Docker** Voici un exemple de commande Docker avec des explications détaillées : ```bash # Télécharger l'image Nginx depuis Docker Hub docker pull nginx # Lancer un conteneur Nginx en arrière-plan (-d) # Rediriger le port 80 du conteneur vers le port 8080 de la machine hôte (-p 8080:80) # Donner un nom au conteneur (--name my-nginx) docker run -d -p 8080:80 --name my-nginx nginx ``` **Explication :** - `docker pull nginx` : Télécharge l’image officielle de Nginx depuis Docker Hub. - `docker run` : Lance un conteneur à partir de l’image. - `-d` : Détache le conteneur (il tourne en arrière-plan). - `-p 8080:80` : Redirige le port 80 du conteneur vers le port 8080 de votre machine. - `--name my-nginx` : Donne un nom au conteneur pour le gérer plus facilement. --- ## **Schéma d’Architecture Docker** ![docker architecture](https://www.whizlabs.com/blog/wp-content/uploads/2019/08/Docker_Architecture.png =x600) --- ## **Exemple Visuel d’un Conteneur en Action** Voici un exemple de ce que vous pouvez montrer pour un conteneur Nginx en action : 1. Lancez le conteneur : ```bash docker run -d -p 8080:80 --name my-nginx nginx ``` 2. Ouvrez votre navigateur et allez à l’adresse `http://localhost:8080`. 3. Vous verrez la page d’accueil de Nginx : ![CleanShot 2025-01-23 at 19.47.45](https://hackmd.io/_uploads/SJw11fgd1l.png) --- ## **Bonus : Liens Utiles** - [Docker Hub](https://hub.docker.com) : Pour explorer des images officielles. - [Documentation Docker](https://docs.docker.com) : Pour approfondir vos connaissances. --- # **Installation et Premiers Pas** --- # **Installer Docker** **Pour commencer avec Docker, vous devez d’abord l’installer sur votre machine.** Voici comment procéder selon votre système d’exploitation : --- ## **1. Sur Linux (Ubuntu/Debian)** 1. Mettez à jour vos paquets : ```bash sudo apt update ``` 2. Installez les dépendances nécessaires : ```bash sudo apt install apt-transport-https ca-certificates curl software-properties-common ``` 3. Ajoutez la clé GPG officielle de Docker : ```bash curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg ``` 4. Ajoutez le dépôt Docker : ```bash echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null ``` 5. Installez Docker : ```bash sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io ``` --- ## **2. Sur macOS** 1. Téléchargez Docker Desktop depuis le site officiel : [https://www.docker.com/products/docker-desktop](https://www.docker.com/products/docker-desktop). 2. Ouvrez le fichier `.dmg` et glissez Docker dans le dossier Applications. 3. Lancez Docker Desktop et suivez les instructions pour compléter l’installation. --- ## **3. Sur Windows** 1. Téléchargez Docker Desktop depuis le site officiel : [https://www.docker.com/products/docker-desktop](https://www.docker.com/products/docker-desktop). 2. Exécutez le fichier d’installation et suivez les étapes. 3. Activez WSL 2 (Windows Subsystem for Linux) si vous utilisez Windows 10/11 pour de meilleures performances. --- ## **Vérifier l’installation** Une fois Docker installé, vérifiez que tout fonctionne correctement : 1. Ouvrez un terminal (ou PowerShell sous Windows). 2. Tapez la commande suivante : ```bash docker --version ``` Vous devriez voir quelque chose comme : ```bash Client: Version: 27.4.1 API version: 1.47 Go version: go1.22.10 ... ``` Cela confirme que Docker est bien installé et prêt à être utilisé. --- ## **Premier Conteneur : Hello World** **C’est l’heure de lancer votre premier conteneur !** 1. Dans votre terminal, exécutez la commande suivante : ```bash docker run hello-world ``` 2. Docker va : - Télécharger l’image `hello-world` depuis Docker Hub (si elle n’est pas déjà présente). - Créer un conteneur à partir de cette image. - Exécuter le conteneur, qui affichera un message de bienvenue. ---- **Résultat attendu :** ```bash Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world c9c5fd25a1bd: Pull complete Digest: sha256:d715f14f9eca81473d9112df50457893aa4d099adeb4729f679006bf5ea12407 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (arm64v8) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/ ``` --- ## **Explication de la Commande `docker run hello-world`** - `docker run` : Lance un conteneur à partir d’une image. - `hello-world` : Le nom de l’image à utiliser. **Ce qui se passe en coulisses :** 1. Docker vérifie si l’image `hello-world` est disponible localement. 2. Si elle n’est pas trouvée, Docker la télécharge depuis Docker Hub. 3. Docker crée un conteneur à partir de cette image et l’exécute. 4. Le conteneur affiche un message, puis s’arrête. --- ## **Résumé de l’Installation** - Vous avez installé Docker sur votre machine. - Vous avez vérifié que Docker fonctionne avec `docker --version`. - Vous avez lancé votre premier conteneur avec `docker run hello-world`. **Prochaine étape :** - Découvrir les commandes Docker essentielles pour gérer vos conteneurs et images. --- # **Commandes Docker Essentielles** --- ## **Gérer les Conteneurs** Docker fournit des commandes simples pour gérer vos conteneurs. Voici les plus importantes : --- ## **1. Lancer un Conteneur : `docker run`** La commande `docker run` permet de créer et de démarrer un conteneur à partir d’une image. **Exemple :** ```bash docker run -d -p 8080:80 --name my-nginx nginx ``` - `-d` : Détache le conteneur (il tourne en arrière-plan). - `-p 8080:80` : Redirige le port 80 du conteneur vers le port 8080 de votre machine. - `--name my-nginx` : Donne un nom au conteneur pour le gérer plus facilement. - `nginx` : L’image à utiliser pour créer le conteneur. --- ## **2. Lister les Conteneurs : `docker ps`** La commande `docker ps` affiche la liste des conteneurs en cours d’exécution. **Exemple :** ```bash docker ps ``` Pour voir tous les conteneurs (y compris ceux arrêtés), ajoutez l’option `-a` : ```bash docker ps -a ``` --- ## **3. Arrêter un Conteneur : `docker stop`** La commande `docker stop` permet d’arrêter un conteneur en cours d’exécution. **Exemple :** ```bash docker stop my-nginx ``` - `my-nginx` : Le nom du conteneur à arrêter. --- ## **4. Supprimer un Conteneur : `docker rm`** La commande `docker rm` supprime un conteneur arrêté. **Exemple :** ```bash docker rm my-nginx ``` - `my-nginx` : Le nom du conteneur à supprimer. **Astuce :** Pour supprimer un conteneur en cours d’exécution, utilisez l’option `-f` : ```bash docker rm -f my-nginx ``` --- ## **5. Interagir avec un Conteneur : `docker exec`** La commande `docker exec` est utilisée pour exécuter une commande à l'intérieur d'un conteneur déjà en cours d'exécution. Cela permet d'interagir avec le conteneur, de diagnostiquer des problèmes, ou d'exécuter des tâches spécifiques sans avoir à redémarrer le conteneur. ##### **Syntaxe de Base** ```bash docker exec [OPTIONS] <container_name_or_id> <command> ``` ##### **Exemples d'Utilisation** 1. **Exécuter une Commande Simple :** ```bash docker exec my-container ls /app ``` 2. **Ouvrir un Shell Interactif :** ```bash docker exec -it my-container bash ``` ---- 3. **Exécuter une Commande en Tant qu'Utilisateur Spécifique :** ```bash docker exec -u www-data my-container whoami ``` 4. **Exécuter une Commande en Arrière-Plan :** ```bash docker exec -d my-container touch /tmp/testfile ``` --- # **Gérer les Images** Les images sont les modèles à partir desquels les conteneurs sont créés. Voici comment les gérer : --- ## **1. Télécharger une Image : `docker pull`** La commande `docker pull` télécharge une image depuis Docker Hub. **Exemple :** ```bash docker pull nginx ``` - `nginx` : Le nom de l’image à télécharger. --- ## **2. Lister les Images : `docker images`** La commande `docker images` affiche la liste des images disponibles localement. **Exemple :** ```bash docker images ``` --- ## **3. Supprimer une Image : `docker rmi`** La commande `docker rmi` supprime une image locale. **Exemple :** ```bash docker rmi nginx ``` - `nginx` : Le nom de l’image à supprimer. **Attention :** Vous ne pouvez pas supprimer une image si un conteneur l’utilise encore. --- ## **Résumé des Commandes Essentielles** | **Commande** | **Description** | **Exemple** | |-----------------------|----------------------------------------------|--------------------------------------| | `docker run` | Lance un conteneur | `docker run -d -p 8080:80 nginx` | | `docker ps` | Liste les conteneurs en cours d’exécution | `docker ps -a` | | `docker stop` | Arrête un conteneur | `docker stop my-nginx` | | `docker rm` | Supprime un conteneur | `docker rm my-nginx` | | `docker pull` | Télécharge une image | `docker pull nginx` | | `docker images` | Liste les images locales | `docker images` | | `docker rmi` | Supprime une image | `docker rmi nginx` | --- # **La Commande `docker run` : Tout ce que vous pouvez faire** La commande `docker run` est l’une des plus puissantes et polyvalentes de Docker. Elle permet de lancer un conteneur avec des options personnalisées pour répondre à des besoins spécifiques. Voici un tour complet de ce que vous pouvez faire avec `docker run` : --- ## **1. Options de Base** ##### **Lancer un Conteneur en Mode Détaché (`-d`)** Pour exécuter un conteneur en arrière-plan : ```bash docker run -d nginx ``` - `-d` : Détache le conteneur (il tourne en arrière-plan). --- ## **Donner un Nom au Conteneur (`--name`)** Pour nommer un conteneur (utile pour le gérer plus facilement) : ```bash docker run --name my-nginx nginx ``` - `--name my-nginx` : Donne le nom `my-nginx` au conteneur. --- ## **Rediriger les Ports (`-p`)** Pour rediriger un port du conteneur vers un port de la machine hôte : ```bash docker run -p 8080:80 nginx ``` - `-p 8080:80` : Redirige le port 80 du conteneur vers le port 8080 de la machine hôte. --- ## **2. Gestion des Volumes** ##### **Monter un Répertoire Local (`-v`)** Pour partager un répertoire local avec le conteneur : ```bash docker run -v /chemin/local:/chemin/conteneur nginx ``` - `-v /chemin/local:/chemin/conteneur` : Monte le répertoire local `/chemin/local` dans le conteneur au chemin `/chemin/conteneur`. **Exemple :** ```bash docker run -v $(pwd)/html:/usr/share/nginx/html nginx ``` - Cela monte le dossier `html` du répertoire courant dans le dossier `/usr/share/nginx/html` du conteneur. --- ## **Utiliser un Volume Docker (`--mount`)** Pour utiliser un volume Docker (persistant) : ```bash docker run --mount source=mon-volume,target=/chemin/conteneur nginx ``` - `source=mon-volume` : Le nom du volume Docker. - `target=/chemin/conteneur` : Le chemin dans le conteneur où le volume est monté. **Exemple :** ```bash docker run --mount source=nginx-data,target=/usr/share/nginx/html nginx ``` --- ## **3. Variables d’Environnement (`-e`)** Pour passer des variables d’environnement au conteneur : ```bash docker run -e VAR_NAME=value nginx ``` - `-e VAR_NAME=value` : Définit la variable d’environnement `VAR_NAME` avec la valeur `value`. **Exemple :** ```bash docker run -e MYSQL_ROOT_PASSWORD=secret mysql ``` - Cela définit le mot de passe root de MySQL à `secret`. --- ## **4. Limiter les Ressources** ##### **Limiter la Mémoire (`-m`)** Pour limiter la mémoire utilisée par le conteneur : ```bash docker run -m 512m nginx ``` - `-m 512m` : Limite la mémoire à 512 Mo. --- ## **Limiter le CPU (`--cpus`)** Pour limiter l’utilisation du CPU : ```bash docker run --cpus="1.5" nginx ``` - `--cpus="1.5"` : Limite l’utilisation à 1,5 cœur de CPU. --- ## **5. Options Avancées** ##### **Exécuter une Commande Spécifique** Pour exécuter une commande spécifique dans le conteneur : ```bash docker run ubuntu echo "Hello, World!" ``` - Cela lance un conteneur Ubuntu, exécute la commande `echo "Hello, World!"`, puis arrête le conteneur. --- ## **Mode Interactif (`-it`)** Pour interagir avec le conteneur via un terminal : ```bash docker run -it ubuntu bash ``` - `-it` : Combine `-i` (interactif) et `-t` (terminal). - `bash` : Ouvre un shell Bash dans le conteneur. --- ## **Supprimer le Conteneur après Exécution (`--rm`)** Pour supprimer automatiquement le conteneur après son arrêt : ```bash docker run --rm nginx ``` - `--rm` : Supprime le conteneur une fois qu’il s’arrête. --- ## **6. Exemple Complet** Voici un exemple combinant plusieurs options : ```bash docker run -d \ --name my-nginx \ -p 8080:80 \ -v $(pwd)/html:/usr/share/nginx/html \ -e NGINX_ENV=production \ --rm \ nginx ``` - `-d` : Détache le conteneur. - `--name my-nginx` : Nomme le conteneur. - `-p 8080:80` : Redirige les ports. - `-v $(pwd)/html:/usr/share/nginx/html` : Monte un répertoire local. - `-e NGINX_ENV=production` : Définit une variable d’environnement. - `--rm` : Supprime le conteneur après arrêt. --- ## **Résumé des Options de `docker run`** | **Option** | **Description** | **Exemple** | |-----------------------|----------------------------------------------|--------------------------------------| | `-d` | Détache le conteneur | `docker run -d nginx` | | `--name` | Donne un nom au conteneur | `docker run --name my-nginx nginx` | | `-p` | Redirige les ports | `docker run -p 8080:80 nginx` | | `-v` | Monte un répertoire local | `docker run -v /chemin:/conteneur` | | `--mount` | Monte un volume Docker | `docker run --mount source=vol` | | `-e` | Définit une variable d’environnement | `docker run -e VAR=value nginx` | | `-m` | Limite la mémoire | `docker run -m 512m nginx` | | `--cpus` | Limite l’utilisation du CPU | `docker run --cpus="1.5" nginx` | | `-it` | Mode interactif avec terminal | `docker run -it ubuntu bash` | | `--rm` | Supprime le conteneur après arrêt | `docker run --rm nginx` | --- # **La Commande `docker exec` : Interagir avec un Conteneur en Cours d'Exécution** La commande `docker exec` est utilisée pour exécuter une commande à l'intérieur d'un conteneur déjà en cours d'exécution. Cela permet d'interagir avec le conteneur, de diagnostiquer des problèmes, ou d'exécuter des tâches spécifiques sans avoir à redémarrer le conteneur. --- ## **1. Syntaxe de Base** La syntaxe générale de la commande `docker exec` est la suivante : ```bash docker exec [OPTIONS] <container_name_or_id> <command> ``` - **`<container_name_or_id>`** : Le nom ou l'ID du conteneur dans lequel vous souhaitez exécuter la commande. - **`<command>`** : La commande à exécuter à l'intérieur du conteneur. --- ## **2. Options Courantes** Voici quelques options couramment utilisées avec `docker exec` : - **`-i` ou `--interactive`** : Garde l'entrée standard (stdin) ouverte, ce qui permet d'interagir avec la commande. - **`-t` ou `--tty`** : Alloue un pseudo-terminal, ce qui est utile pour les commandes interactives comme un shell. - **`-d` ou `--detach`** : Exécute la commande en arrière-plan (détachée). - **`-u` ou `--user`** : Exécute la commande en tant qu'un utilisateur spécifique. --- ## **3. Exemples d'Utilisation** ### **Exécuter une Commande Simple** Pour exécuter une commande simple à l'intérieur d'un conteneur, par exemple, afficher la liste des fichiers dans un répertoire : ```bash docker exec my-container ls /app ``` - `my-container` : Le nom du conteneur. - `ls /app` : La commande à exécuter. --- ### **Ouvrir un Shell Interactif** Pour ouvrir un shell interactif à l'intérieur d'un conteneur (par exemple, `bash` ou `sh`) : ```bash docker exec -it my-container bash ``` - `-it` : Combine les options `-i` (interactif) et `-t` (terminal). - `bash` : Le shell à exécuter. **Remarque :** Si le conteneur n'a pas `bash` installé, vous pouvez utiliser `sh` à la place. --- ### **Exécuter une Commande en Tant qu'Utilisateur Spécifique** Pour exécuter une commande en tant qu'un utilisateur spécifique (par exemple, l'utilisateur `www-data`) : ```bash docker exec -u www-data my-container whoami ``` - `-u www-data` : Exécute la commande en tant que l'utilisateur `www-data`. - `whoami` : La commande à exécuter. --- ### **Exécuter une Commande en Arrière-Plan** Pour exécuter une commande en arrière-plan (détachée) : ```bash docker exec -d my-container touch /tmp/testfile ``` - `-d` : Exécute la commande en arrière-plan. - `touch /tmp/testfile` : La commande à exécuter. --- ## **4. Cas d'Usage Courants** ### **Diagnostiquer des Problèmes** Si un conteneur ne fonctionne pas comme prévu, vous pouvez utiliser `docker exec` pour inspecter les logs, vérifier les fichiers de configuration, ou tester des commandes spécifiques. **Exemple :** ```bash docker exec -it my-container tail -f /var/log/nginx/error.log ``` - Cela affiche les logs d'erreur de Nginx en temps réel. --- ### **Modifier des Fichiers dans un Conteneur** Vous pouvez utiliser `docker exec` pour éditer des fichiers directement dans un conteneur. **Exemple :** ```bash docker exec -it my-container vi /etc/nginx/nginx.conf ``` - Cela ouvre le fichier de configuration de Nginx dans l'éditeur `vi`. --- ### **Installer des Paquets ou des Dépendances** Si vous avez besoin d'installer des paquets supplémentaires dans un conteneur, vous pouvez utiliser `docker exec` pour exécuter les commandes d'installation. **Exemple :** ```bash docker exec -it my-container apt-get update docker exec -it my-container apt-get install -y curl ``` - Cela met à jour les paquets et installe `curl` dans le conteneur. --- ## **5. Bonnes Pratiques** - **Évitez de Modifier les Conteneurs en Production :** Les modifications apportées via `docker exec` ne sont pas persistantes. Si vous devez modifier un conteneur, il est préférable de recréer l'image et de redéployer le conteneur. - **Utilisez des Commandes Non Destructives :** Évitez d'exécuter des commandes qui pourraient endommager le conteneur ou l'application en cours d'exécution. - **Limitez l'Accès :** Si vous utilisez `docker exec` pour accéder à un conteneur en production, assurez-vous de limiter l'accès aux utilisateurs autorisés. --- ## **6. Résumé des Commandes** | **Commande** | **Description** | |---------------------------------------|----------------------------------------------| | `docker exec my-container ls /app` | Liste les fichiers dans `/app` | | `docker exec -it my-container bash` | Ouvre un shell interactif dans le conteneur | | `docker exec -u www-data my-container whoami` | Exécute `whoami` en tant que `www-data` | | `docker exec -d my-container touch /tmp/testfile` | Crée un fichier en arrière-plan | --- ## **Conclusion** La commande `docker exec` est un outil puissant pour interagir avec des conteneurs en cours d'exécution. Que ce soit pour diagnostiquer des problèmes, exécuter des commandes spécifiques, ou ouvrir un shell interactif, `docker exec` est indispensable pour tout utilisateur de Docker. En suivant les bonnes pratiques, vous pouvez utiliser cette commande de manière efficace et sécurisée pour gérer vos conteneurs. --- # **Volumes Docker, Réseaux Docker et Autres Fonctionnalités Avancées** Docker offre des fonctionnalités puissantes pour gérer les données persistantes (volumes) et la communication entre conteneurs (réseaux). Voici un guide complet pour maîtriser ces concepts. --- ## **1. Volumes Docker** Les volumes Docker permettent de **persister les données** générées par les conteneurs, même après leur suppression. Ils sont essentiels pour les bases de données, les fichiers de configuration, ou tout autre type de données critiques. --- ## **Pourquoi Utiliser des Volumes ?** - Les conteneurs sont éphémères : si vous supprimez un conteneur, toutes ses données sont perdues. - Les volumes permettent de stocker les données en dehors du conteneur, sur la machine hôte ou dans un espace géré par Docker. --- ## **Types de Volumes** 1. **Volumes Docker** : Gérés par Docker, stockés dans un répertoire spécifique sur la machine hôte. 2. **Bind Mounts** : Lient un répertoire spécifique de la machine hôte à un répertoire du conteneur. 3. **tmpfs Mounts** : Stockent les données en mémoire vive (RAM). --- ## **Créer et Utiliser un Volume Docker** 1. Créez un volume : ```bash docker volume create mon-volume ``` 2. Utilisez le volume dans un conteneur : ```bash docker run -d --name my-nginx -v mon-volume:/usr/share/nginx/html nginx ``` - `-v mon-volume:/usr/share/nginx/html` : Monte le volume `mon-volume` dans le répertoire `/usr/share/nginx/html` du conteneur. ---- 3. Lister les volumes : ```bash docker volume ls ``` 4. Inspecter un volume : ```bash docker volume inspect mon-volume ``` 5. Supprimer un volume : ```bash docker volume rm mon-volume ``` --- ## **Utiliser un Bind Mount** Un **bind mount** lie un répertoire spécifique de la machine hôte à un répertoire du conteneur. **Exemple :** ```bash docker run -d --name my-nginx -v /chemin/local:/usr/share/nginx/html nginx ``` - `/chemin/local` : Le répertoire local sur la machine hôte. - `/usr/share/nginx/html` : Le répertoire dans le conteneur. --- ## **Utiliser un tmpfs Mount** Un **tmpfs mount** stocke les données en mémoire vive (RAM). **Exemple :** ```bash docker run -d --name my-nginx --tmpfs /tmp nginx ``` - `/tmp` : Le répertoire dans le conteneur où les données seront stockées en RAM. --- ## **2. Réseaux Docker** Les réseaux Docker permettent aux conteneurs de **communiquer entre eux** de manière sécurisée et isolée. Docker fournit plusieurs types de réseaux pour répondre à différents besoins. --- ## **Types de Réseaux** 1. **Bridge** : Le réseau par défaut. Les conteneurs peuvent communiquer entre eux, mais pas avec l’extérieur. 2. **Host** : Le conteneur utilise directement le réseau de la machine hôte. 3. **Overlay** : Permet à plusieurs hôtes Docker de communiquer (utilisé avec Docker Swarm). 4. **Macvlan** : Donne une adresse MAC unique à chaque conteneur, le faisant apparaître comme un appareil physique sur le réseau. 5. **None** : Désactive le réseau pour le conteneur. --- ## **Créer et Utiliser un Réseau Bridge** 1. Créez un réseau : ```bash docker network create mon-reseau ``` 2. Lancez des conteneurs sur ce réseau : ```bash docker run -d --name my-nginx --network mon-reseau nginx docker run -d --name my-mysql --network mon-reseau mysql ``` - Les conteneurs `my-nginx` et `my-mysql` peuvent communiquer entre eux via le réseau `mon-reseau`. 3. Inspecter un réseau : ```bash docker network inspect mon-reseau ``` 4. Supprimer un réseau : ```bash docker network rm mon-reseau ``` --- ## **Utiliser le Réseau Host** Pour que le conteneur utilise directement le réseau de la machine hôte : ```bash docker run -d --name my-nginx --network host nginx ``` - Le conteneur sera accessible via l’adresse IP de la machine hôte. --- ## **Utiliser le Réseau None** Pour désactiver le réseau pour un conteneur : ```bash docker run -d --name my-nginx --network none nginx ``` - Le conteneur n’aura pas accès au réseau. --- ## **3. Autres Fonctionnalités Avancées** --- ## **Limiter les Ressources** Vous pouvez limiter les ressources (CPU, mémoire) utilisées par un conteneur. **Exemple :** ```bash docker run -d --name my-nginx --cpus="1.5" -m "512m" nginx ``` - `--cpus="1.5"` : Limite l’utilisation à 1,5 cœur de CPU. - `-m "512m"` : Limite la mémoire à 512 Mo. --- ## **Exécuter une Commande Spécifique** Pour exécuter une commande spécifique dans un conteneur : ```bash docker run ubuntu echo "Hello, World!" ``` - Cela lance un conteneur Ubuntu, exécute la commande `echo "Hello, World!"`, puis arrête le conteneur. --- ## **Résumé des Fonctionnalités** | **Fonctionnalité** | **Description** | **Exemple** | |--------------------------|----------------------------------------------|--------------------------------------| | **Volumes Docker** | Persister les données | `docker volume create mon-volume` | | **Bind Mounts** | Lier un répertoire local | `docker run -v /chemin:/conteneur` | | **Réseaux Docker** | Communication entre conteneurs | `docker network create mon-reseau` | | **Limiter les Ressources**| Limiter CPU/mémoire | `docker run --cpus="1.5" -m "512m"` | | **Variables d’Environnement** | Passer des variables | `docker run -e VAR=value` | --- # **Utilisation de `docker stats` pour Surveiller les Conteneurs** La commande `docker stats` est un outil puissant pour surveiller en temps réel les **ressources système** utilisées par vos conteneurs. Elle affiche des informations telles que l’utilisation du CPU, de la mémoire, du réseau, et des E/S disque. --- ## **1. Utilisation de Base** Pour afficher les statistiques en temps réel de tous les conteneurs en cours d’exécution : ```bash docker stats ``` **Exemple de Sortie :** ``` CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS a1b2c3d4e5f6 my-nginx 0.12% 25.3MiB / 1.944GiB 1.27% 1.23kB / 0B 0B / 0B 2 b2c3d4e5f6a7 my-mysql 1.45% 120.5MiB / 1.944GiB 6.05% 5.67MB / 2.34MB 0B / 0B 10 ``` --- ## **2. Options Avancées** ## **Afficher des Conteneurs Spécifiques** Pour surveiller uniquement certains conteneurs, listez leurs noms ou IDs : ```bash docker stats my-nginx my-mysql ``` --- ## **Afficher les Statistiques sans Stream** Pour afficher les statistiques une seule fois (sans mise à jour en temps réel) : ```bash docker stats --no-stream ``` --- ## **Afficher Tous les Conteneurs (Même Arrêtés)** Pour inclure les conteneurs arrêtés dans les statistiques : ```bash docker stats --all ``` --- ## **Changer le Format de Sortie** Vous pouvez personnaliser le format de sortie en utilisant l’option `--format`. **Exemple :** ```bash docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" ``` - `{{.Name}}` : Nom du conteneur. - `{{.CPUPerc}}` : Pourcentage d’utilisation du CPU. - `{{.MemUsage}}` : Utilisation de la mémoire. **Sortie :** ``` NAME CPU % MEM USAGE / LIMIT my-nginx 0.12% 25.3MiB / 1.944GiB my-mysql 1.45% 120.5MiB / 1.944GiB ``` --- ## **3. Explication des Colonnes** | **Colonne** | **Description** | |-------------------|----------------------------------------------| | `CONTAINER ID` | Identifiant unique du conteneur. | | `NAME` | Nom du conteneur. | | `CPU %` | Pourcentage d’utilisation du CPU. | | `MEM USAGE / LIMIT` | Mémoire utilisée par rapport à la limite. | | `MEM %` | Pourcentage de mémoire utilisée. | | `NET I/O` | Données réseau entrantes/sortantes. | | `BLOCK I/O` | Données disque entrantes/sortantes. | | `PIDS` | Nombre de processus dans le conteneur. | --- ## **6. Résumé des Options de `docker stats`** | **Option** | **Description** | **Exemple** | |---------------------|----------------------------------------------|--------------------------------------| | `--no-stream` | Affiche les statistiques une seule fois | `docker stats --no-stream` | | `--all` | Inclut les conteneurs arrêtés | `docker stats --all` | | `--format` | Personnalise le format de sortie | `docker stats --format "table {{.Name}}"` | --- # **Play with Docker : Une Plateforme pour Apprendre et Tester Docker** **Play with Docker** (PWD) est une plateforme en ligne gratuite qui permet d’apprendre, de tester et d’expérimenter avec Docker sans avoir à installer quoi que ce soit sur votre machine. C’est un outil idéal pour les débutants et les développeurs qui veulent se familiariser avec Docker dans un environnement sécurisé et isolé. --- ## **1. Qu’est-ce que Play with Docker ?** - **Environnement Docker en Ligne :** PWD fournit un environnement Docker complet dans votre navigateur. Vous pouvez exécuter des commandes Docker, créer des conteneurs, et même utiliser Docker Compose. - **Sessions Temporaires :** Chaque session dure 4 heures, ce qui est largement suffisant pour la plupart des exercices et démonstrations. - **Interface Utilisateur Simple :** PWD offre une interface web intuitive avec un terminal intégré pour exécuter des commandes Docker. --- ## **2. Comment Accéder à Play with Docker ?** 1. Rendez-vous sur le site officiel : [https://labs.play-with-docker.com/](https://labs.play-with-docker.com/). 2. Cliquez sur **"Start"** pour démarrer une nouvelle session. 3. Connectez-vous avec votre compte Docker Hub (ou créez-en un gratuitement). 4. Une fois connecté, vous accédez à une interface avec un terminal et des options pour ajouter des instances Docker. --- #### **8. Ressources Utiles** - **Documentation Docker :** [https://docs.docker.com/](https://docs.docker.com/) - **Tutoriels Docker :** [https://training.play-with-docker.com/](https://training.play-with-docker.com/) --- # **Les Tags dans Docker : Gérer les Versions des Images** Un **tag** est une étiquette associée à une image Docker. Il permet de versionner les images et de spécifier quelle version d’une image vous souhaitez utiliser. Par défaut, si vous ne spécifiez pas de tag, Docker utilise le tag `latest`. --- ## **1. Pourquoi Utiliser des Tags ?** - **Gestion des Versions :** Les tags permettent de différencier les versions d’une même image (ex : `v1.0`, `v2.0`). - **Reproductibilité :** En spécifiant un tag, vous vous assurez que votre application utilise toujours la même version d’une image. - **Stabilité :** Évite les surprises liées aux mises à jour automatiques de l’image `latest`. --- ## **2. Tags Prédéfinis** - **`latest` :** Le tag par défaut. Il pointe généralement vers la dernière version stable d’une image. **Exemple :** ```bash docker pull nginx:latest ``` - **Tags de Version :** Les images officielles ont souvent des tags spécifiques pour chaque version. **Exemple :** ```bash docker pull nginx:1.23.4 ``` - **Tags Basés sur le Système d’Exploitation :** Certaines images ont des tags spécifiques pour différents systèmes d’exploitation (ex : `alpine`, `buster`). **Exemple :** ```bash docker pull python:3.8-slim ``` --- ## **3. Utilisation des Tags** --- ## **Télécharger une Image avec un Tag Spécifique** Pour télécharger une image avec un tag spécifique : ```bash docker pull <nom-image>:<tag> ``` **Exemple :** ```bash docker pull nginx:1.23.4 ``` --- ## **Lister les Tags Disponibles** Pour voir les tags disponibles pour une image, vous pouvez : 1. Visiter la page de l’image sur [Docker Hub](https://hub.docker.com). 2. Utiliser des outils en ligne de commande comme `curl` ou `skopeo`. **Exemple avec `curl` :** ```bash curl -s "https://registry.hub.docker.com/v2/repositories/library/nginx/tags/" | jq -r '.results[].name' ``` --- ## **Créer un Tag Personnalisé** Vous pouvez créer un tag personnalisé pour une image locale. **Exemple :** ```bash docker tag nginx:1.23.4 mon-nginx:v1 ``` - Cela crée un nouveau tag `mon-nginx:v1` pour l’image `nginx:1.23.4`. --- ## **Pousser une Image avec un Tag** Pour pousser une image avec un tag vers un registre Docker (ex : Docker Hub) : ```bash docker tag mon-nginx:v1 mon-utilisateur/mon-nginx:v1 docker push mon-utilisateur/mon-nginx:v1 ``` --- ## **4. Bonnes Pratiques pour les Tags** 1. **Évitez `latest` en Production :** Utilisez des tags spécifiques pour éviter les mises à jour imprévues. 2. **Utilisez des Tags Sémantiques :** Suivez le versionnement sémantique (ex : `v1.2.3`) pour clarifier les versions. 3. **Tags pour les Environnements :** Utilisez des tags comme `dev`, `staging`, ou `prod` pour différencier les environnements. --- ## **5. Exemple Pratique** **Scénario :** Vous développez une application Python et souhaitez utiliser une version spécifique de l’image Python. 1. Téléchargez l’image Python 3.8 avec le tag `slim` : ```bash docker pull python:3.8-slim ``` 2. Créez un tag personnalisé pour cette image : ```bash docker tag python:3.8-slim mon-python:dev ``` 3. Vérifiez que le tag a bien été créé : ```bash docker images ``` 4. Utilisez l’image avec le tag personnalisé dans un conteneur : ```bash docker run -it mon-python:dev python --version ``` --- #### **6. Résumé des Commandes liées aux Tags** | **Commande** | **Description** | **Exemple** | |-----------------------------|----------------------------------------------|--------------------------------------| | `docker pull <image>:<tag>` | Télécharge une image avec un tag spécifique | `docker pull nginx:1.23.4` | | `docker tag <image> <tag>` | Crée un nouveau tag pour une image locale | `docker tag nginx:1.23.4 mon-nginx:v1` | | `docker push <image>:<tag>` | Pousse une image avec un tag vers un registre| `docker push mon-utilisateur/mon-nginx:v1` | --- # **Dockerfile : Créer ses Images** Le **Dockerfile** est un fichier texte qui contient toutes les instructions nécessaires pour créer une image Docker. Il permet de définir l’environnement d’exécution d’une application, d’installer des dépendances, et de configurer le conteneur. --- ## **Structure d’un Dockerfile** Un Dockerfile est composé d’une série d’instructions, chacune représentant une étape dans la construction de l’image. Chaque instruction crée une **couche** (layer) dans l’image, ce qui permet à Docker de réutiliser les couches pour optimiser la construction des images. --- ## **Commandes Dockerfile Essentielles** Voici les commandes les plus couramment utilisées dans un Dockerfile : --- ## **1. `FROM`** - **Description :** Spécifie l’image de base à utiliser pour construire votre image. - **Exemple :** ```dockerfile FROM python:3.8-slim ``` - Utilise l’image officielle Python 3.8 avec une version légère (`slim`). --- ## **2. `WORKDIR`** - **Description :** Définit le répertoire de travail dans le conteneur. Toutes les commandes suivantes seront exécutées dans ce répertoire. - **Exemple :** ```dockerfile WORKDIR /app ``` - Définit `/app` comme répertoire de travail. --- ## **3. `COPY`** - **Description :** Copie des fichiers ou répertoires de la machine hôte vers le conteneur. - **Exemple :** ```dockerfile COPY . . ``` - Copie tous les fichiers du répertoire courant de la machine hôte vers le répertoire de travail du conteneur. --- ## **4. `RUN`** - **Description :** Exécute une commande dans le conteneur pendant la construction de l’image. - **Exemple :** ```dockerfile RUN pip install --no-cache-dir -r requirements.txt ``` - Installe les dépendances Python listées dans `requirements.txt`. --- ## **5. `CMD`** - **Description :** Définit la commande par défaut à exécuter lorsque le conteneur démarre. Il ne peut y avoir qu’une seule instruction `CMD` dans un Dockerfile. - **Exemple :** ```dockerfile CMD ["python", "app.py"] ``` - Exécute `python app.py` lorsque le conteneur démarre. --- ## **6. `EXPOSE`** - **Description :** Indique les ports sur lesquels le conteneur écoutera. Cela ne publie pas automatiquement les ports ; vous devez utiliser l’option `-p` avec `docker run`. - **Exemple :** ```dockerfile EXPOSE 5000 ``` - Indique que le conteneur écoute sur le port 5000. --- ## **7. `ENV`** - **Description :** Définit des variables d’environnement dans le conteneur. - **Exemple :** ```dockerfile ENV FLASK_ENV=production ``` - Définit la variable d’environnement `FLASK_ENV` à `production`. --- ## **8. `ARG`** - **Description :** Définit des variables utilisables uniquement pendant la construction de l’image. - **Exemple :** ```dockerfile ARG APP_VERSION=1.0 ``` - Définit une variable `APP_VERSION` avec la valeur par défaut `1.0`. --- ## **9. `VOLUME`** - **Description :** Crée un point de montage pour un volume Docker. - **Exemple :** ```dockerfile VOLUME /data ``` - Crée un volume monté sur `/data`. --- ## **10. `ENTRYPOINT`** - **Description :** Similaire à `CMD`, mais permet de définir une commande de base qui ne peut pas être facilement remplacée. - **Exemple :** ```dockerfile ENTRYPOINT ["python"] CMD ["app.py"] ``` - Exécute `python app.py` par défaut, mais permet de passer d’autres arguments. --- ## **Exemple : Dockeriser une Application Python Simple** Voici un exemple complet de Dockerfile pour une application Python Flask : ---- ## **1. Structure du Projet** ``` flask-app/ ├── app.py ├── requirements.txt └── Dockerfile ``` --- ## **2. Fichier `app.py`** ```python from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello, Docker!" if __name__ == '__main__': app.run(host='0.0.0.0') ``` --- ## **3. Fichier `requirements.txt`** ``` Flask==2.3.2 ``` --- ## **4. Fichier `Dockerfile`** ```dockerfile # Étape 1 : Utiliser une image de base Python FROM python:3.8-slim # Étape 2 : Définir le répertoire de travail WORKDIR /app # Étape 3 : Copier les fichiers de l'application COPY requirements.txt . COPY app.py . # Étape 4 : Installer les dépendances RUN pip install --no-cache-dir -r requirements.txt # Étape 5 : Exposer le port 5000 EXPOSE 5000 # Étape 6 : Définir la commande par défaut CMD ["python", "app.py"] ``` --- ## **5. Construire et Lancer l’Image** 1. Construisez l’image : ```bash docker build -t my-flask-app . ``` 2. Lancez le conteneur : ```bash docker run -d -p 5000:5000 --name my-flask-container my-flask-app ``` 3. Accédez à l’application : - Ouvrez votre navigateur et allez à `http://localhost:5000`. - Vous devriez voir le message `Hello, Docker!`. --- ## **Bonnes Pratiques pour les Dockerfiles** 1. **Minimiser le Nombre de Couches :** Combinez les commandes `RUN` pour réduire le nombre de couches. **Exemple :** ```dockerfile RUN apt-get update && apt-get install -y \ package1 \ package2 \ && rm -rf /var/lib/apt/lists/* ``` 2. **Utiliser des Images de Base Légères :** Préférez des images comme `alpine` ou `slim` pour réduire la taille de l’image. 3. **Utiliser `.dockerignore` :** Créez un fichier `.dockerignore` pour exclure des fichiers inutiles (comme `node_modules`, `.git`, etc.). 4. **Éviter `latest` :** Utilisez des tags spécifiques pour les images de base (ex : `python:3.8-slim`). --- ## **Exemple de `.dockerignore`** ``` node_modules .git *.log ``` --- ## **Résumé des Commandes Dockerfile** | **Commande** | **Description** | **Exemple** | |----------------|----------------------------------------------|--------------------------------------| | `FROM` | Image de base | `FROM python:3.8-slim` | | `WORKDIR` | Répertoire de travail | `WORKDIR /app` | | `COPY` | Copier des fichiers | `COPY . .` | | `RUN` | Exécuter une commande | `RUN pip install -r requirements.txt`| | `CMD` | Commande par défaut | `CMD ["python", "app.py"]` | | `EXPOSE` | Exposer un port | `EXPOSE 5000` | | `ENV` | Définir une variable d’environnement | `ENV FLASK_ENV=production` | | `ARG` | Définir une variable de construction | `ARG APP_VERSION=1.0` | | `VOLUME` | Créer un volume | `VOLUME /data` | | `ENTRYPOINT` | Définir une commande de base | `ENTRYPOINT ["python"]` | --- # **Différence entre `ENTRYPOINT` et `CMD`** --- ## **1. `CMD` : Commande Par Défaut** - **Rôle :** Définit la commande par défaut du conteneur. - **Comportement :** - Les arguments passés à `docker run` **remplacent** entièrement `CMD`. **Exemple :** ```dockerfile CMD ["python", "app.py"] ``` - `docker run my-image echo "Hello"` → Exécute `echo "Hello"` (remplace `CMD`). --- ## **2. `ENTRYPOINT` : Commande de Base** - **Rôle :** Définit une commande de base qui ne change pas. - **Comportement :** - Les arguments passés à `docker run` sont **ajoutés** à `ENTRYPOINT`. **Exemple :** ```dockerfile ENTRYPOINT ["python"] ``` - `docker run my-image app.py` → Exécute `python app.py` (ajoute `app.py` à `ENTRYPOINT`). --- ## **3. Combinaison `ENTRYPOINT` + `CMD`** - **Rôle :** `ENTRYPOINT` définit la commande de base, `CMD` fournit des arguments par défaut. - **Comportement :** - Les arguments de `docker run` remplacent `CMD`, mais pas `ENTRYPOINT`. **Exemple :** ```dockerfile ENTRYPOINT ["python"] CMD ["app.py"] ``` - `docker run my-image` → Exécute `python app.py`. - `docker run my-image script.py` → Exécute `python script.py`. --- ## **4. Quand Utiliser ?** - **`CMD` :** Pour une commande par défaut facilement remplaçable. - **`ENTRYPOINT` :** Pour une commande de base fixe avec des arguments variables. --- ## **Résumé en Une Ligne** - **`CMD`** : Commande par défaut, remplaçable. - **`ENTRYPOINT`** : Commande de base, arguments ajoutés. --- # **Introduction à Docker Compose** Docker Compose est un outil qui permet de définir et de gérer des applications multi-conteneurs. Il utilise un fichier YAML (`docker-compose.yml`) pour configurer les services, les réseaux, et les volumes nécessaires au fonctionnement de l’application. --- ## **1. Pourquoi Docker Compose ?** - **Simplifier la Gestion des Multi-Conteneurs :** Au lieu de lancer manuellement plusieurs conteneurs avec `docker run`, Docker Compose permet de tout gérer en une seule commande. - **Reproductibilité :** Le fichier `docker-compose.yml` décrit l’ensemble de l’environnement, ce qui rend l’application facile à déployer sur n’importe quelle machine. - **Orchestration :** Docker Compose gère les dépendances entre les services (ex : une base de données doit démarrer avant une application web). - **Développement Local :** Idéal pour créer des environnements de développement locaux avec plusieurs services (ex : web, base de données, cache). --- ## **2. Structure d’un Fichier `docker-compose.yml`** Un fichier `docker-compose.yml` est organisé en sections principales : --- ## **Version** Spécifie la version du format de fichier. ```yaml version: '3.8' ``` :::info Ce n'est plus obligatoire depuis la version **1.27.0** de docker compose. ::: --- ## **Services** Définit les conteneurs (services) qui composent l’application. Chaque service peut inclure : - **`image`** : L’image Docker à utiliser. - **`build`** : Le chemin vers un Dockerfile pour construire une image personnalisée. - **`ports`** : Redirige les ports du conteneur vers la machine hôte. - **`volumes`** : Monte des répertoires ou des volumes Docker. - **`environment`** : Définit des variables d’environnement. - **`depends_on`** : Spécifie les dépendances entre services. **Exemple :** ```yaml services: web: image: nginx ports: - "8080:80" db: image: mysql environment: MYSQL_ROOT_PASSWORD: secret ``` --- ## **Volumes** Définit des volumes persistants pour stocker des données. ```yaml volumes: db-data: ``` --- ## **Réseaux** Définit des réseaux personnalisés pour connecter les services. ```yaml networks: my-network: ``` --- ## **3. Exemple : Déployer une Stack Web + Base de Données** Voici un exemple concret pour déployer une application web Flask avec une base de données MySQL. --- ## **Structure du Projet** ``` flask-mysql-app/ ├── app/ │ ├── app.py │ ├── requirements.txt │ └── Dockerfile └── docker-compose.yml ``` --- ## **Fichier `app.py`** ```python from flask import Flask import mysql.connector app = Flask(__name__) # Configuration de la base de données db_config = { 'user': 'root', 'password': 'secret', 'host': 'db', 'database': 'mydb', 'raise_on_warnings': True } @app.route('/') def hello(): # Connexion à la base de données conn = mysql.connector.connect(**db_config) cursor = conn.cursor() cursor.execute("SELECT * FROM messages") result = cursor.fetchall() conn.close() return f"Messages: {result}" if __name__ == '__main__': app.run(host='0.0.0.0') ``` --- ## **Fichier `requirements.txt`** ``` Flask==2.3.2 mysql-connector-python==8.0.33 ``` --- ## **Fichier `Dockerfile`** ```dockerfile FROM python:3.8-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "app.py"] ``` --- ## **Fichier `docker-compose.yml`** ```yaml version: '3.8' services: web: build: ./app ports: - "5000:5000" depends_on: - db environment: FLASK_ENV: development db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: mydb volumes: - db-data:/var/lib/mysql volumes: db-data: ``` --- Ah, je vois ! Tu veux que je remplace la section **"Déployer la Stack"** et **"Résumé des Commandes Docker Compose"** en expliquant à la fois l’ancienne version (`docker-compose`) et la nouvelle version (`docker compose`). Voici la version adaptée : --- ## **Déployer la Stack** ### **Ancienne Version (`docker-compose`)** 1. Dans le répertoire du projet, exécutez : ```bash docker-compose up -d ``` 2. Vérifiez que les services sont en cours d’exécution : ```bash docker-compose ps ``` 3. Accédez à l’application web : - Ouvrez votre navigateur et allez à `http://localhost:5000`. 4. Arrêtez la stack : ```bash docker-compose down ``` --- ## **Nouvelle Version (`docker compose`)** 1. Dans le répertoire du projet, exécutez : ```bash docker compose up -d ``` 2. Vérifiez que les services sont en cours d’exécution : ```bash docker compose ps ``` 3. Accédez à l’application web : - Ouvrez votre navigateur et allez à `http://localhost:5000`. 4. Arrêtez la stack : ```bash docker compose down ``` --- ## **Résumé des Commandes Docker Compose** ### **Ancienne Version (`docker-compose`)** | **Commande** | **Description** | |-----------------------------|----------------------------------------------| | `docker-compose up -d` | Démarre les services en arrière-plan | | `docker-compose down` | Arrête et supprime les services | | `docker-compose ps` | Affiche l’état des services | | `docker-compose logs` | Affiche les logs des services | | `docker-compose build` | Reconstruit les images | --- ### **Nouvelle Version (`docker compose`)** | **Commande** | **Description** | |-----------------------------|----------------------------------------------| | `docker compose up -d` | Démarre les services en arrière-plan | | `docker compose down` | Arrête et supprime les services | | `docker compose ps` | Affiche l’état des services | | `docker compose logs` | Affiche les logs des services | | `docker compose build` | Reconstruit les images | --- ## **Différences Clés entre les Deux Versions** 1. **Syntaxe :** - Ancienne : `docker-compose` (avec un tiret). - Nouvelle : `docker compose` (sans tiret, intégrée à Docker CLI). 2. **Installation :** - Ancienne : Nécessitait une installation séparée (via `pip` ou un package manager). - Nouvelle : Intégrée directement dans Docker Desktop (à partir de la version 20.10.0). 3. **Performances :** - La nouvelle version est plus rapide et plus efficace. 4. **Fonctionnalités :** - La nouvelle version introduit des fonctionnalités avancées comme les **profils** et une meilleure gestion des **secrets**. --- ## **Quand Utiliser l’Ancienne ou la Nouvelle Version ?** - **Ancienne Version (`docker-compose`) :** - Si vous travaillez sur un ancien système où Docker Compose V2 n’est pas disponible. - Si vous avez des scripts ou des workflows existants qui utilisent `docker-compose`. - **Nouvelle Version (`docker compose`) :** - Pour tous les nouveaux projets. - Pour profiter des dernières fonctionnalités et améliorations. --- ## **Comment Savoir Quelle Version Vous Utilisez ?** 1. Vérifiez la version de Docker Compose : ```bash docker compose version ``` - Si vous voyez une version (ex : `Docker Compose version v2.1.1`), vous utilisez la nouvelle version. 2. Si la commande `docker compose` n’est pas reconnue : - Assurez-vous que Docker Desktop est à jour (version 20.10.0 ou supérieure). - Activez Docker Compose V2 dans les paramètres de Docker Desktop (si nécessaire). --- ## **Conclusion** - **`docker compose`** est la nouvelle façon recommandée d’utiliser Docker Compose. - Elle est plus simple, plus performante, et intégrée directement dans Docker CLI. - Si vous utilisez encore `docker-compose`, il est temps de migrer vers `docker compose` pour profiter des dernières fonctionnalités. --- ## **5. Pourquoi Utiliser Docker Compose ?** - **Simplicité :** Une seule commande pour démarrer tous les services. - **Portabilité :** Le fichier `docker-compose.yml` peut être partagé et utilisé sur n’importe quelle machine. - **Orchestration :** Gère les dépendances entre les services (ex : la base de données démarre avant l’application web). --- # **Prochaine étape : Explorer des Fonctionnalités Avancées de Docker Compose** Maintenant que vous maîtrisez les bases de Docker Compose, voici quelques fonctionnalités avancées que vous pouvez explorer pour améliorer vos déploiements et gérer vos applications de manière plus professionnelle. --- ## **1. Scaling (Mise à l’Échelle des Services)** Docker Compose permet de **scaler** (mettre à l’échelle) un service pour exécuter plusieurs instances d’un même conteneur. Cela est utile pour gérer la charge ou améliorer la disponibilité. --- ## **Comment Scaler un Service ?** Utilisez l’option `--scale` avec la commande `docker compose up`. **Exemple :** ```bash docker compose up -d --scale web=3 ``` - Cela lance 3 instances du service `web`. --- ## **Limitations :** - Le scaling fonctionne mieux avec des services **stateless** (sans état). - Pour les services **stateful** (comme une base de données), il faut une configuration supplémentaire (ex : clustering). --- ## **2. Health Checks (Vérifications de Santé)** Les **health checks** permettent de surveiller l’état de santé d’un service. Si un conteneur ne répond pas aux critères de santé, Docker Compose peut le redémarrer automatiquement. --- ## **Comment Configurer un Health Check ?** Ajoutez une section `healthcheck` dans votre fichier `docker-compose.yml`. **Exemple :** ```yaml services: web: image: nginx healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 ``` - **`test`** : La commande à exécuter pour vérifier la santé (ici, `curl -f http://localhost`). - **`interval`** : Temps entre deux vérifications (30 secondes). - **`timeout`** : Temps d’attente avant de considérer la vérification comme un échec (10 secondes). - **`retries`** : Nombre de tentatives avant de considérer le conteneur comme défaillant (3). --- ## **Voir l’État de Santé :** Utilisez la commande suivante pour vérifier l’état de santé des services : ```bash docker compose ps ``` - Vous verrez une colonne **STATUS** indiquant l’état de santé (ex : `healthy`, `unhealthy`). --- ## **3. Secrets (Gestion des Données Sensibles)** Docker Compose permet de gérer les **secrets** (mots de passe, clés API, etc.) de manière sécurisée. Les secrets sont stockés dans des fichiers ou des services de gestion de secrets (ex : Docker Swarm). --- ## **Comment Utiliser des Secrets ?** 1. Créez un fichier de secret (ex : `db_password.txt`) : ```bash echo "mon_mot_de_passe_secret" > db_password.txt ``` 2. Définissez le secret dans votre fichier `docker-compose.yml` : ```yaml services: db: image: mysql environment: MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_password secrets: - db_password secrets: db_password: file: ./db_password.txt ``` 3. Le secret sera accessible dans le conteneur via le fichier `/run/secrets/db_password`. --- ## **4. Profils (Profiles)** Les **profils** permettent de définir des groupes de services à démarrer ensemble. Cela est utile pour gérer des environnements différents (ex : développement, test, production). --- ## **Comment Utiliser des Profils ?** Ajoutez une section `profiles` dans votre fichier `docker-compose.yml`. **Exemple :** ```yaml services: web: image: nginx profiles: ["dev"] db: image: mysql profiles: ["dev", "prod"] cache: image: redis profiles: ["prod"] ``` - Démarrer uniquement les services du profil `dev` : ```bash docker compose --profile dev up ``` - Démarrer tous les services (sans spécifier de profil) : ```bash docker compose up ``` --- ## **5. Réseaux Personnalisés** Docker Compose permet de créer des **réseaux personnalisés** pour isoler les services ou configurer des connexions spécifiques. --- ## **Comment Créer un Réseau Personnalisé ?** Ajoutez une section `networks` dans votre fichier `docker-compose.yml`. **Exemple :** ```yaml services: web: image: nginx networks: - frontend db: image: mysql networks: - backend networks: frontend: backend: ``` - Les services `web` et `db` sont isolés dans des réseaux différents. --- ## **6. Volumes Nommés** Les **volumes nommés** permettent de persister les données de manière plus contrôlée. Ils sont gérés par Docker et peuvent être réutilisés entre différents conteneurs. --- ## **Comment Utiliser un Volume Nommé ?** Ajoutez une section `volumes` dans votre fichier `docker-compose.yml`. **Exemple :** ```yaml services: db: image: mysql volumes: - db-data:/var/lib/mysql volumes: db-data: ``` - Le volume `db-data` est utilisé pour persister les données de la base de données. --- ## **Résumé des Fonctionnalités Avancées** | **Fonctionnalité** | **Description** | **Exemple** | |--------------------------|----------------------------------------------|--------------------------------------| | **Scaling** | Mettre à l’échelle un service | `docker compose up --scale web=3` | | **Health Checks** | Vérifier l’état de santé des services | `healthcheck: test: ["CMD", "curl"]` | | **Secrets** | Gérer les données sensibles | `secrets: db_password: file: ./.env` | | **Profils** | Grouper des services par environnement | `profiles: ["dev", "prod"]` | | **Réseaux Personnalisés**| Isoler ou connecter des services | `networks: frontend:` | | **Volumes Nommés** | Persister les données de manière contrôlée | `volumes: db-data:` | --- ## **Conclusion** - **Scaling** : Pour gérer la charge avec plusieurs instances d’un service. - **Health Checks** : Pour surveiller et maintenir la disponibilité des services. - **Secrets** : Pour gérer les données sensibles de manière sécurisée. - **Profils** : Pour organiser les services par environnement. - **Réseaux et Volumes** : Pour une gestion avancée des connexions et des données. Ces fonctionnalités vous permettront de créer des déploiements plus robustes, sécurisés et adaptés à vos besoins. --- ### **Fonctionnalités Avancées de Docker Compose : `watch` et `env_file`** Docker Compose offre des fonctionnalités supplémentaires pour améliorer votre workflow de développement et de déploiement. Parmi celles-ci, **`watch`** et **`env_file`** sont particulièrement utiles pour automatiser des tâches et gérer les variables d’environnement de manière efficace. --- ## **1. `watch` : Surveiller les Changements et Redémarrer Automatiquement** La fonctionnalité **`watch`** (introduite dans Docker Compose **v2.22.0**) permet de surveiller les fichiers locaux et de redémarrer automatiquement les services lorsque des modifications sont détectées. C’est idéal pour le développement, car cela évite de redémarrer manuellement les conteneurs après chaque changement de code. --- ## **Comment Utiliser `watch` ?** 1. Ajoutez une section `watch` dans votre fichier `docker-compose.yml` pour spécifier les fichiers ou répertoires à surveiller. 2. Définissez l’action à effectuer lors d’un changement (ex : redémarrer le service, reconstruire l’image). **Exemple :** ```yaml services: web: build: . ports: - "5000:5000" develop: watch: - action: sync path: ./app target: /app - action: rebuild path: ./Dockerfile ``` - **`action: sync`** : Synchronise les fichiers locaux (`./app`) avec le répertoire `/app` dans le conteneur. - **`action: rebuild`** : Reconstruit l’image si le fichier `Dockerfile` est modifié. --- ## **Démarrer avec `watch` :** Utilisez la commande suivante pour activer la surveillance : ```bash docker compose watch ``` - Docker Compose surveillera les fichiers spécifiés et appliquera les actions automatiquement. --- ## **Cas d’Usage :** - **Développement d’applications web :** Synchronisez les fichiers de code source avec le conteneur pour voir les changements en temps réel. - **Tests automatisés :** Redémarrez les services lorsque les tests ou les configurations sont modifiés. --- ## **2. `env_file` : Gérer les Variables d’Environnement avec des Fichiers** La fonctionnalité **`env_file`** permet de charger des variables d’environnement à partir d’un fichier externe (ex : `.env`). Cela est utile pour centraliser la configuration et éviter de hardcoder des informations sensibles dans le fichier `docker-compose.yml`. --- ## **Comment Utiliser `env_file` ?** 1. Créez un fichier `.env` dans le répertoire de votre projet : ```bash DB_USER=admin DB_PASSWORD=secret DB_HOST=db ``` 2. Référencez ce fichier dans votre fichier `docker-compose.yml` : ```yaml services: web: image: my-app env_file: - .env db: image: mysql environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} ``` - Les variables définies dans `.env` seront injectées dans les services. --- ## **Avantages de `env_file` :** - **Centralisation :** Toutes les variables sont stockées dans un seul fichier. - **Sécurité :** Évitez de hardcoder des informations sensibles dans le fichier `docker-compose.yml`. - **Flexibilité :** Utilisez des fichiers `.env` différents pour chaque environnement (ex : `.env.dev`, `.env.prod`). --- ## **Exemple avec Plusieurs Fichiers `.env` :** Vous pouvez charger plusieurs fichiers `.env` pour des environnements différents : ```yaml services: web: image: my-app env_file: - .env.dev - .env.secrets ``` - Les variables seront fusionnées, avec priorité donnée au dernier fichier listé. --- ## **Utilisation des Variables dans `docker-compose.yml` :** Vous pouvez référencer les variables directement dans le fichier `docker-compose.yml` : ```yaml services: db: image: mysql environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} ``` - Si la variable `DB_PASSWORD` est définie dans `.env`, elle sera injectée ici. --- ## **3. Combinaison de `watch` et `env_file`** Vous pouvez combiner `watch` et `env_file` pour créer un environnement de développement dynamique et configurable. **Exemple :** ```yaml services: web: build: . ports: - "5000:5000" env_file: - .env.dev develop: watch: - action: sync path: ./app target: /app ``` - Les variables d’environnement sont chargées depuis `.env.dev`. - Les fichiers de l’application sont synchronisés avec le conteneur en temps réel. --- ### **Résumé des Fonctionnalités** | **Fonctionnalité** | **Description** | **Exemple** | |--------------------------|----------------------------------------------|--------------------------------------| | **`watch`** | Surveille les fichiers et redémarre les services automatiquement | `watch: action: sync` | | **`env_file`** | Charge les variables d’environnement depuis un fichier externe | `env_file: .env` | --- ## **Conclusion** - **`watch`** : Automatise les redémarrages et les synchronisations pour un développement plus fluide. - **`env_file`** : Centralise et sécurise la gestion des variables d’environnement. Ces fonctionnalités vous permettent de gagner du temps, d’améliorer la sécurité et de rendre vos déploiements plus flexibles. --- # **Exploration Avancée des Volumes et Réseaux dans Docker Compose** Les **volumes** et les **réseaux** sont deux fonctionnalités puissantes de Docker Compose qui permettent de gérer les données persistantes et la communication entre les services de manière flexible et efficace. Voici un aperçu détaillé des possibilités offertes par ces fonctionnalités. --- ## **1. Volumes dans Docker Compose** Les volumes permettent de **persister les données** générées par les conteneurs, même après leur suppression. Ils sont essentiels pour les bases de données, les fichiers de configuration, ou tout autre type de données critiques. --- ## **Types de Volumes** 1. **Volumes Nommés :** - Gérés par Docker, stockés dans un répertoire spécifique sur la machine hôte. - Idéal pour les données persistantes partagées entre plusieurs conteneurs. 2. **Bind Mounts :** - Lient un répertoire spécifique de la machine hôte à un répertoire du conteneur. - Utile pour le développement, car les modifications sont immédiatement visibles. 3. **Volumes Temporaires (`tmpfs`) :** - Stockent les données en mémoire vive (RAM). - Idéal pour les données temporaires qui ne doivent pas persister. --- ## **Utilisation des Volumes dans Docker Compose** ###### **Volumes Nommés** 1. Définissez un volume nommé dans la section `volumes` : ```yaml volumes: db-data: ``` 2. Montez le volume dans un service : ```yaml services: db: image: mysql volumes: - db-data:/var/lib/mysql ``` - Les données de MySQL seront stockées dans le volume `db-data`. --- ## **Bind Mounts** 1. Montez un répertoire local dans un conteneur : ```yaml services: web: image: nginx volumes: - ./html:/usr/share/nginx/html ``` - Le répertoire `./html` sur la machine hôte est monté dans `/usr/share/nginx/html` du conteneur. --- ## **Volumes Temporaires (`tmpfs`)** 1. Utilisez `tmpfs` pour stocker des données en mémoire : ```yaml services: cache: image: redis tmpfs: - /data ``` - Les données Redis seront stockées en mémoire vive. --- ## **Options Avancées des Volumes** - **Mode d’Accès :** Contrôlez les permissions d’accès au volume. **Exemple :** ```yaml volumes: - ./data:/app/data:ro ``` - `ro` : Lecture seule. - **Driver :** Utilisez un driver spécifique pour gérer les volumes (ex : `local`, `nfs`). **Exemple :** ```yaml volumes: db-data: driver: local driver_opts: type: nfs o: addr=192.168.1.1,rw device: ":/path/to/nfs" ``` --- ## **2. Réseaux dans Docker Compose** Les réseaux permettent aux conteneurs de **communiquer entre eux** de manière sécurisée et isolée. Docker Compose crée automatiquement un réseau par défaut, mais vous pouvez aussi définir des réseaux personnalisés. --- ## **Types de Réseaux** 1. **Réseau Bridge (Par Défaut) :** - Les conteneurs peuvent communiquer entre eux, mais pas avec l’extérieur. - Idéal pour les applications mono-hôte. 2. **Réseau Host :** - Le conteneur utilise directement le réseau de la machine hôte. - Utile pour des performances maximales, mais moins sécurisé. 3. **Réseau Overlay :** - Permet à plusieurs hôtes Docker de communiquer (utilisé avec Docker Swarm). 4. **Réseau Macvlan :** - Donne une adresse MAC unique à chaque conteneur, le faisant apparaître comme un appareil physique sur le réseau. --- ## **Utilisation des Réseaux dans Docker Compose** ### **Réseau Bridge Personnalisé** 1. Créez un réseau personnalisé : ```yaml networks: frontend: driver: bridge ``` 2. Attachez les services au réseau : ```yaml services: web: image: nginx networks: - frontend db: image: mysql networks: - backend networks: frontend: backend: ``` - Les services `web` et `db` sont isolés dans des réseaux différents. --- ## **Réseau Host** 1. Utilisez le réseau `host` pour un service : ```yaml services: web: image: nginx network_mode: host ``` - Le conteneur utilise directement le réseau de la machine hôte. --- ## **Options Avancées des Réseaux** - **Alias :** Donnez un alias à un service pour faciliter la communication. **Exemple :** ```yaml services: web: image: nginx networks: frontend: aliases: - app ``` - Le service `web` sera accessible via l’alias `app`. - **IPAM (IP Address Management) :** Configurez manuellement les adresses IP. **Exemple :** ```yaml networks: frontend: ipam: config: - subnet: 172.20.0.0/16 gateway: 172.20.0.1 ``` --- ## **3. Combinaison de Volumes et Réseaux** Vous pouvez combiner volumes et réseaux pour créer des environnements complexes et performants. **Exemple :** ```yaml services: web: image: nginx volumes: - ./html:/usr/share/nginx/html networks: - frontend db: image: mysql volumes: - db-data:/var/lib/mysql networks: - backend volumes: db-data: networks: frontend: backend: ``` - Le service `web` utilise un bind mount pour les fichiers HTML et est connecté au réseau `frontend`. - Le service `db` utilise un volume nommé pour les données et est connecté au réseau `backend`. --- ## **Résumé des Fonctionnalités** | **Fonctionnalité** | **Description** | **Exemple** | |--------------------------|----------------------------------------------|--------------------------------------| | **Volumes Nommés** | Persister les données | `volumes: db-data:` | | **Bind Mounts** | Lier un répertoire local | `volumes: ./html:/app` | | **Volumes Temporaires** | Stocker des données en mémoire | `tmpfs: /data` | | **Réseau Bridge** | Communication entre conteneurs | `networks: frontend:` | | **Réseau Host** | Utiliser le réseau de la machine hôte | `network_mode: host` | | **Alias** | Donner un alias à un service | `aliases: ["app"]` | --- ## **Conclusion** - **Volumes :** Pour persister les données, partager des fichiers, ou stocker des données temporaires. - **Réseaux :** Pour isoler les services, configurer des connexions spécifiques, ou optimiser les performances. Ces fonctionnalités vous permettent de créer des environnements Docker Compose robustes, flexibles et adaptés à vos besoins. --- # **Bonnes Pratiques et Pièges à Éviter avec Docker** Pour tirer le meilleur parti de Docker tout en évitant les erreurs courantes, voici une liste de **bonnes pratiques** et de **pièges à éviter**. Ces conseils vous aideront à créer des conteneurs plus sécurisés, performants et faciles à maintenir. --- ## **1. Utiliser des Images Officielles** --- ## **Pourquoi ?** - Les images officielles sont maintenues par des organisations reconnues (ex : Docker, Inc., les mainteneurs de logiciels open source). - Elles sont régulièrement mises à jour pour corriger les vulnérabilités de sécurité. - Elles suivent les meilleures pratiques en matière de configuration et d’optimisation. --- ## **Comment Faire ?** - Utilisez des images officielles disponibles sur [Docker Hub](https://hub.docker.com/). - Vérifiez les tags pour choisir une version spécifique (ex : `nginx:1.23.4` au lieu de `nginx:latest`). **Exemple :** ```dockerfile FROM python:3.8-slim ``` - Utilise l’image officielle Python avec une version légère (`slim`). --- ## **Piège à Éviter :** - Évitez les images non officielles ou non vérifiées, car elles peuvent contenir des vulnérabilités ou des logiciels malveillants. --- ## **2. Optimiser les Images Docker** --- ## **Pourquoi ?** - Des images optimisées sont plus petites, plus rapides à télécharger et à déployer. - Elles réduisent la surface d’attaque en limitant les composants installés. --- ## **Comment Faire ?** ###### **Utiliser des Images de Base Légères** - Préférez des images de base comme `alpine`, `slim`, ou `buster-slim`. **Exemple :** ```dockerfile FROM python:3.8-alpine ``` - Utilise une image Alpine, connue pour sa petite taille. --- ## **Minimiser le Nombre de Couches** - Combinez les commandes `RUN` pour réduire le nombre de couches dans l’image. **Exemple :** ```dockerfile RUN apt-get update && apt-get install -y \ package1 \ package2 \ && rm -rf /var/lib/apt/lists/* ``` - Supprime les fichiers temporaires après l’installation pour réduire la taille de l’image. --- ## **Utiliser un `.dockerignore`** - Créez un fichier `.dockerignore` pour exclure les fichiers inutiles (ex : `node_modules`, `.git`). **Exemple :** ``` node_modules .git *.log ``` --- ## **Utiliser des Builds Multi-Étapes** - Utilisez des builds multi-étapes pour séparer l’environnement de construction de l’environnement d’exécution. **Exemple :** ```dockerfile # Étape de construction FROM python:3.8-slim AS builder COPY requirements.txt . RUN pip install --user -r requirements.txt # Étape d’exécution FROM python:3.8-slim COPY --from=builder /root/.local /root/.local COPY . . CMD ["python", "app.py"] ``` --- ## **Piège à Éviter :** - Évitez d’installer des packages inutiles ou de laisser des fichiers temporaires dans l’image finale. --- ## **3. Sécurité : Éviter les Conteneurs "root"** --- ## **Pourquoi ?** - Exécuter un conteneur en tant qu’utilisateur `root` (par défaut) peut poser des risques de sécurité. - Si un attaquant compromet le conteneur, il pourrait avoir un accès complet au système hôte. --- ## **Comment Faire ?** ### **Utiliser un Utilisateur Non Root** - Créez un utilisateur non root dans le Dockerfile et utilisez-le pour exécuter l’application. **Exemple :** ```dockerfile FROM python:3.8-slim # Crée un utilisateur non root RUN useradd -m myuser # Définit l’utilisateur par défaut USER myuser # Définit le répertoire de travail WORKDIR /app # Copie les fichiers et installe les dépendances COPY --chown=myuser:myuser . . RUN pip install --no-cache-dir -r requirements.txt # Commande par défaut CMD ["python", "app.py"] ``` --- ### **Limiter les Permissions** - Utilisez des volumes en mode lecture seule (`ro`) pour limiter les accès. **Exemple :** ```yaml volumes: - ./data:/app/data:ro ``` --- ### **Utiliser des Contextes Sécurisés** - Activez les fonctionnalités de sécurité comme **AppArmor**, **Seccomp**, ou **SELinux** pour limiter les actions du conteneur. **Exemple :** ```yaml services: web: image: nginx security_opt: - seccomp:unconfined ``` --- ## **Piège à Éviter :** - Ne laissez jamais un conteneur s’exécuter en tant que `root` sans raison valable. --- ## **4. Autres Bonnes Pratiques** --- ## **Utiliser des Variables d’Environnement** - Stockez les informations sensibles (mots de passe, clés API) dans des variables d’environnement ou des fichiers `.env`. **Exemple :** ```yaml services: db: image: mysql environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} ``` --- ## **Mettre à Jour Régulièrement les Images** - Utilisez des images à jour pour bénéficier des correctifs de sécurité et des améliorations. **Exemple :** ```bash docker pull nginx:latest ``` --- ## **Limiter les Ressources** - Utilisez des limites de ressources (CPU, mémoire) pour éviter qu’un conteneur monopolise les ressources du système. **Exemple :** ```yaml services: web: image: nginx deploy: resources: limits: cpus: '0.5' memory: 512M ``` --- ## **Résumé des Bonnes Pratiques** | **Bonnes Pratiques** | **Description** | **Exemple** | |------------------------------|----------------------------------------------|--------------------------------------| | **Utiliser des images officielles** | Préférez les images officielles pour la sécurité et la stabilité | `FROM python:3.8-slim` | | **Optimiser les images** | Réduisez la taille et la surface d’attaque | `RUN apt-get update && apt-get install` | | **Éviter les conteneurs root**| Exécutez les conteneurs avec un utilisateur non root | `USER myuser` | | **Utiliser des variables d’environnement** | Stockez les informations sensibles de manière sécurisée | `environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}` | | **Mettre à jour les images** | Utilisez des images à jour pour les correctifs de sécurité | `docker pull nginx:latest` | --- ## **Conclusion** En suivant ces bonnes pratiques, vous pouvez créer des conteneurs Docker plus **sécurisés**, **performants** et **faciles à maintenir**. Évitez les pièges courants comme l’utilisation d’images non officielles, l’exécution en tant que `root`, ou la création d’images trop volumineuses. --- # **Utilisation des Images `scratch` dans Docker** L’image **`scratch`** est une image Docker spéciale qui est **vide** : elle ne contient aucun fichier, aucune bibliothèque, et aucun système d’exploitation. Elle est utilisée pour créer des conteneurs extrêmement légers, souvent pour des applications statiquement compilées (comme des binaires Go ou C). --- ## **1. Pourquoi Utiliser `scratch` ?** - **Taille Minimale :** Les conteneurs basés sur `scratch` sont les plus légers possibles, car ils ne contiennent que l’application elle-même. - **Sécurité :** Moins de composants signifient moins de vulnérabilités potentielles. - **Performances :** Les conteneurs basés sur `scratch` démarrent plus rapidement et utilisent moins de ressources. --- ## **2. Quand Utiliser `scratch` ?** - **Applications Statiquement Compilées :** Si votre application est compilée de manière statique (c’est-à-dire qu’elle inclut toutes les dépendances nécessaires dans le binaire), vous pouvez l’exécuter dans un conteneur basé sur `scratch`. - **Binaires Autonomes :** Les langages comme Go ou Rust permettent de créer des binaires autonomes qui n’ont pas besoin de dépendances externes. --- ## **3. Comment Utiliser `scratch` ?** Voici un exemple simple pour créer une image Docker basée sur `scratch` pour une application Go. --- ## **Étape 1 : Créer un Binaire Statique** 1. Écrivez un programme Go simple : ```go package main import "fmt" func main() { fmt.Println("Hello, from a scratch container!") } ``` 2. Compilez le programme en un binaire statique : ```bash CGO_ENABLED=0 GOOS=linux go build -o myapp -a -installsuffix cgo . ``` - `CGO_ENABLED=0` : Désactive les liaisons dynamiques (pour un binaire statique). - `GOOS=linux` : Spécifie que le binaire est pour Linux (le système d’exploitation de Docker). --- ## **Étape 2 : Créer un Dockerfile** 1. Créez un fichier `Dockerfile` : ```dockerfile FROM scratch COPY myapp /myapp CMD ["/myapp"] ``` - `FROM scratch` : Utilise l’image `scratch` comme base. - `COPY myapp /myapp` : Copie le binaire dans le conteneur. - `CMD ["/myapp"]` : Exécute le binaire au démarrage du conteneur. 2. Construisez l’image Docker : ```bash docker build -t my-scratch-app . ``` 3. Lancez le conteneur : ```bash docker run my-scratch-app ``` - Vous devriez voir le message : `Hello, from a scratch container!` --- ## **4. Limitations de `scratch`** - **Pas de Shell :** L’image `scratch` ne contient pas de shell (`/bin/sh`), donc vous ne pouvez pas exécuter de commandes interactives dans le conteneur. - **Pas de Bibliothèques Système :** Si votre application dépend de bibliothèques système (ex : `glibc`), elle ne fonctionnera pas avec `scratch`. - **Pas de Gestionnaire de Paquets :** Vous ne pouvez pas installer de packages supplémentaires dans un conteneur basé sur `scratch`. --- ## **5. Alternatives à `scratch`** Si `scratch` est trop minimaliste pour vos besoins, voici quelques alternatives légères : - **`alpine` :** Une image Linux ultra-légère (environ 5 Mo) avec un shell et un gestionnaire de paquets (`apk`). - **`distroless` (Google) :** Des images minimalistes conçues pour exécuter des applications spécifiques (ex : Java, Python, Node.js). **Exemple avec `alpine` :** ```dockerfile FROM alpine:latest COPY myapp /myapp CMD ["/myapp"] ``` --- ## **6. Cas d’Usage de `scratch`** - **Applications Go Statiques :** Les binaires Go sont souvent compilés de manière statique, ce qui les rend parfaits pour `scratch`. - **Outils en Ligne de Commande :** Les outils autonomes comme `curl` ou `jq` peuvent être exécutés dans un conteneur `scratch`. - **Environnements de Production :** Pour des applications critiques où la sécurité et les performances sont prioritaires. --- ## **7. Exemple Complet** Voici un exemple complet pour une application Go : --- ## **Fichier `main.go`** ```go package main import "fmt" func main() { fmt.Println("Hello, from a scratch container!") } ``` --- ## **Fichier `Dockerfile`** ```dockerfile FROM scratch COPY myapp /myapp CMD ["/myapp"] ``` --- ## **Étapes pour Construire et Exécuter** 1. Compilez le programme Go : ```bash CGO_ENABLED=0 GOOS=linux go build -o myapp -a -installsuffix cgo . ``` 2. Construisez l’image Docker : ```bash docker build -t my-scratch-app . ``` 3. Lancez le conteneur : ```bash docker run my-scratch-app ``` --- ## **Résumé** - **`scratch`** est une image vide, idéale pour les applications statiquement compilées. - Elle permet de créer des conteneurs extrêmement légers et sécurisés. - Utilisez `scratch` pour des applications autonomes, mais optez pour `alpine` ou `distroless` si vous avez besoin d’un shell ou de bibliothèques système. --- # **Conclusion et Aller Plus Loin** --- ## **Avantages de Docker et Docker Compose** Docker et Docker Compose sont des outils puissants qui ont révolutionné la manière dont les applications sont développées, déployées et gérées. Voici un résumé de leurs principaux avantages : --- ## **1. Docker** - **Isolation :** Chaque application tourne dans son propre environnement isolé, évitant les conflits de dépendances. - **Portabilité :** Les conteneurs Docker fonctionnent de la même manière sur n’importe quelle machine (Linux, macOS, Windows). - **Efficacité :** Les conteneurs sont légers et partagent le noyau de l’OS hôte, ce qui les rend plus rapides et moins gourmands en ressources que les machines virtuelles. - **Écosystème :** Docker Hub offre des milliers d’images officielles et communautaires pour accélérer le développement. --- ## **2. Docker Compose** - **Orchestration Simplifiée :** Permet de gérer plusieurs conteneurs (services) avec un seul fichier de configuration (`docker-compose.yml`). - **Reproductibilité :** Le fichier `docker-compose.yml` décrit l’ensemble de l’environnement, ce qui rend l’application facile à déployer partout. - **Développement Local :** Idéal pour créer des environnements de développement locaux avec plusieurs services (ex : web, base de données, cache). - **Intégration Continue :** Facilite les tests et les déploiements automatisés. --- ## **Ressources pour Approfondir** Pour aller plus loin dans votre apprentissage de Docker et Docker Compose, voici quelques ressources utiles : --- ## **1. Documentation Officielle** - **Docker :** [https://docs.docker.com/](https://docs.docker.com/) - Guides, références API, et tutoriels pour maîtriser Docker. - **Docker Compose :** [https://docs.docker.com/compose/](https://docs.docker.com/compose/) - Documentation complète sur Docker Compose, y compris des exemples avancés. --- ## **2. Tutoriels et Cours en Ligne** - **Docker pour Débutants (en français) :** [https://openclassrooms.com/fr/courses/2035766-optimisez-votre-deploiement-en-creant-des-conteneurs-avec-docker](https://openclassrooms.com/fr/courses/2035766-optimisez-votre-deploiement-en-creant-des-conteneurs-avec-docker) - Un cours complet pour apprendre Docker de A à Z. - **Play with Docker (PWD) :** [https://labs.play-with-docker.com/](https://labs.play-with-docker.com/) - Une plateforme en ligne pour tester Docker sans rien installer. - **Docker Mastery (Udemy) :** [https://www.udemy.com/course/docker-mastery/](https://www.udemy.com/course/docker-mastery/) - Un cours payant, mais très complet, pour devenir un expert Docker. --- ## **3. Communautés et Forums** - **Docker Community Forums :** [https://forums.docker.com/](https://forums.docker.com/) - Un espace pour poser des questions et partager des connaissances. - **Stack Overflow :** [https://stackoverflow.com/questions/tagged/docker](https://stackoverflow.com/questions/tagged/docker) - Des milliers de questions et réponses sur Docker. - **Reddit :** [https://www.reddit.com/r/docker/](https://www.reddit.com/r/docker/) - Une communauté active pour discuter de Docker et de ses utilisations. --- ## **4. Livres** - **"Docker Deep Dive" par Nigel Poulton :** Un livre complet pour comprendre Docker en profondeur. - **"Docker in Action" par Jeff Nickoloff et Stephen Kuenzli :** Un guide pratique pour maîtriser Docker dans des scénarios réels. --- ## **5. Projets Open Source** - Explorez des projets open source utilisant Docker pour voir des exemples concrets : - [https://github.com/docker/awesome-compose](https://github.com/docker/awesome-compose) - [https://github.com/docker-library](https://github.com/docker-library) --- ## **6. Vidéos et Conférences** - **DockerCon :** [https://www.docker.com/dockercon/](https://www.docker.com/dockercon/) - La conférence annuelle de Docker, avec des présentations et des démos. - **YouTube :** Recherchez des chaînes comme **Docker** ou **The Net Ninja** pour des tutoriels vidéo. --- ## **Prochaines Étapes** 1. **Expérimentez :** - Créez vos propres images Docker et fichiers `docker-compose.yml`. - Dockerisez une application existante. 2. **Explorez des Fonctionnalités Avancées :** - Utilisez Docker Swarm ou Kubernetes pour orchestrer des conteneurs à grande échelle. - Explorez Docker Security Scanning pour sécuriser vos images. 3. **Contribuez à la Communauté :** - Partagez vos images sur Docker Hub. - Contribuez à des projets open source liés à Docker. --- ## **Conclusion** Docker et Docker Compose sont des outils indispensables pour tout développeur ou administrateur système. Ils simplifient le développement, le déploiement et la gestion des applications, tout en améliorant la portabilité et la sécurité. En explorant les ressources mentionnées ci-dessus, vous pourrez approfondir vos connaissances et devenir un expert en conteneurisation. --- # **Docker Compose pour une Application Java avec GraalVM, Redis, et PostgreSQL** Voici un exemple complet de fichier `docker-compose.yml` pour une application Java compilée avec **GraalVM** en un binaire natif, utilisant **Redis** pour le cache et **PostgreSQL** pour la base de données. Ce fichier intègre des **bonnes pratiques de sécurité** et utilise des **variables d’environnement** pour gérer les informations sensibles. --- ## **Structure du Projet** ``` java-app/ ├── src/ │ └── Main.java ├── Dockerfile ├── docker-compose.yml ├── .env └── redis.conf ``` --- ## **1. Fichier `.env`** Stockez les informations sensibles dans un fichier `.env` : ```bash # Variables pour PostgreSQL POSTGRES_DB=mydb POSTGRES_USER=admin POSTGRES_PASSWORD=secret # Variables pour Redis REDIS_PASSWORD=redispass # Variables pour l'application Java APP_PORT=8080 ``` --- ## **2. Fichier `docker-compose.yml`** ```yaml services: app: build: context: . dockerfile: Dockerfile ports: - "${APP_PORT}:8080" environment: - DATABASE_URL=jdbc:postgresql://db:5432/${POSTGRES_DB} - DATABASE_USER=${POSTGRES_USER} - DATABASE_PASSWORD=${POSTGRES_PASSWORD} - REDIS_HOST=redis - REDIS_PASSWORD=${REDIS_PASSWORD} depends_on: - db - redis networks: - backend db: image: postgres:13-alpine environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres-data:/var/lib/postgresql/data networks: - backend healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 ``` --- ```yaml! redis: image: redis:6-alpine command: redis-server --requirepass ${REDIS_PASSWORD} volumes: - ./redis.conf:/usr/local/etc/redis/redis.conf networks: - backend healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 volumes: postgres-data: networks: backend: driver: bridge ``` --- ## **3. Fichier `Dockerfile`** Créez un binaire natif avec GraalVM et utilisez l’image `scratch` pour l’exécuter : ```dockerfile # Étape 1 : Utiliser GraalVM pour compiler l'application FROM ghcr.io/graalvm/native-image:22.3.1 AS builder WORKDIR /app COPY src/ /app/src/ RUN javac src/Main.java RUN native-image -H:Name=myapp -H:Class=Main --static -H:+ReportExceptionStackTraces # Étape 2 : Utiliser l'image scratch pour exécuter le binaire FROM scratch COPY --from=builder /app/myapp /myapp CMD ["/myapp"] ``` --- ## **4. Fichier `redis.conf`** Configurez Redis pour une meilleure sécurité : ```conf bind 127.0.0.1 protected-mode yes requirepass ${REDIS_PASSWORD} ``` --- ## **5. Fichier `Main.java`** Exemple d’application Java qui utilise PostgreSQL et Redis : ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import redis.clients.jedis.Jedis; public class Main { public static void main(String[] args) { String dbUrl = System.getenv("DATABASE_URL"); String dbUser = System.getenv("DATABASE_USER"); String dbPassword = System.getenv("DATABASE_PASSWORD"); String redisHost = System.getenv("REDIS_HOST"); String redisPassword = System.getenv("REDIS_PASSWORD"); try { // Connexion à PostgreSQL Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT version()"); if (rs.next()) { System.out.println("PostgreSQL version: " + rs.getString(1)); } ``` --- ```java // Connexion à Redis Jedis jedis = new Jedis(redisHost); jedis.auth(redisPassword); jedis.set("key", "Hello, Redis!"); System.out.println("Redis value: " + jedis.get("key")); // Fermer les connexions rs.close(); stmt.close(); conn.close(); jedis.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` --- ## **6. Déployer la Stack** 1. Compilez l’application Java en un binaire natif : ```bash docker build -t my-java-app . ``` 2. Démarrez la stack avec Docker Compose : ```bash docker compose up -d ``` 3. Vérifiez que les services sont en cours d’exécution : ```bash docker compose ps ``` 4. Accédez aux logs de l’application : ```bash docker compose logs -f app ``` 5. Arrêtez la stack : ```bash docker compose down ``` --- ## **7. Sécurité et Bonnes Pratiques** - **Variables d’Environnement :** Les informations sensibles (mots de passe, clés) sont stockées dans un fichier `.env` et injectées via des variables d’environnement. - **Health Checks :** PostgreSQL et Redis ont des vérifications de santé pour s’assurer qu’ils sont prêts à accepter des connexions. - **Volumes :** Les données de PostgreSQL sont persistées dans un volume nommé (`postgres-data`). - **Configuration Redis :** Le fichier `redis.conf` sécurise Redis en activant le mode protégé et en exigeant un mot de passe. - **Image `scratch` :** L’application Java est compilée en un binaire natif et exécutée dans une image `scratch`, ce qui la rend légère et sécurisée. --- ## **Résumé des Commandes** | **Commande** | **Description** | |-----------------------------|----------------------------------------------| | `docker compose up -d` | Démarre la stack en arrière-plan | | `docker compose down` | Arrête et supprime les services | | `docker compose logs -f app`| Affiche les logs de l’application | | `docker compose ps` | Affiche l’état des services | --- ## **Conclusion** Ce fichier `docker-compose.yml` montre comment déployer une application Java compilée avec GraalVM, utilisant Redis et PostgreSQL, tout en intégrant des bonnes pratiques de sécurité. En utilisant des **variables d’environnement**, des **health checks**, et des **images minimalistes** comme `scratch`, vous pouvez créer des déploiements robustes, sécurisés et performants.
{"title":"Docker","description":"Formation Docker","lang":"fr-FR","robots":"noindex, nofollow","slideOptions":"{\"fragments\":false,\"transition\":\"fade\",\"backgroundTransition\":\"fade\",\"slideNumber\":true,\"previewLinks\":true,\"progress\":true,\"width\":1366,\"height\":768,\"overview\":true,\"mouseWheel\":true}","contributors":"[{\"id\":\"35198f6d-8c66-4636-8d98-b19eb0b4c48c\",\"add\":125989,\"del\":26110}]","showTags":"true"}
    102 views