ajout dev docker

This commit is contained in:
EmmanuelTiamzon
2026-06-04 18:57:15 +02:00
parent 2d17b25873
commit d12a1adb6d
34 changed files with 1255 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
# BUT2FA-DOCKER
## Ce dépôt git contient le dossier de chaque TP :
* TP1 L'introduction au cycle de vie des dockers et la différenciation des conteneurs et des images
* TP2 Les volumes et bind-mounts
+213
View File
@@ -0,0 +1,213 @@
# Commandes utilisées - TP1
## 2. Installation
### 2.2 Vérification de l'installation :
```shell
sudo docker --version
# Docker version 28.3.3, build 980b856816
sudo docker run hello-world
# Unable to find image 'hello-world:latest' locally
# latest: Pulling from library/hello-world
# 4f55086f7dd0: Pull complete
# Digest: sha256:452a468a4bf985040037cb6d5392410206e47db9bf5b7278d281f94d1c2d0931
# Status: Downloaded newer image for hello-world:latest
# Hello from Docker!
```
## 3 Premiers pas avec Docker
### 3.1 Images Docker
### 3.1.1 Lister les images disponibles
```shell
sudo docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# hello-world latest e2ac70e7319a 2 weeks ago 10.1kB
# prog_python latest 3dabe55bd71c 7 weeks ago 1.12GB
# <none> <none> 21d22a499c76 7 weeks ago 1.12GB
# python 3.15-rc-trixie 3bf0ec7eb030 2 months ago 1.12GB
# imunes/template latest 58009592de73 2 years ago 387MB
```
### 3.1.2 Télécharger une image
```shell
sudo docker pull nginx
# Using default tag: latest
# latest: Pulling from library/nginx
# 5435b2dcdf5c: Pull complete
# 054715a6bffa: Pull complete
# 88d1d984b765: Pull complete
# 4a038fd18db1: Pull complete
# 84e114c2bb36: Pull complete
# 7b5d674621c2: Pull complete
# 448ea5cac5d5: Pull complete
# Digest: sha256:7f0adca1fc6c29c8dc49a2e90037a10ba20dc266baaed0988e9fb4d0d8b85ba0
# Status: Downloaded newer image for nginx:latest
# docker.io/library/nginx:latest
```
### 3.1.3 Rechercher une image
```shell
sudo docker search ubuntu
# NAME DESCRIPTION STARS OFFICIAL
# ubuntu Ubuntu is a Debian-based Linux operating sys… 17808 [OK]
# ubuntu/squid Squid is a caching proxy for the Web. Long-t… 125
# ...
```
## 3.2 Gestion basique des conteneurs
1. Créer un premier conteneur :
```shell
docker run nginx
# Il tente de start le process/conteneur nginx et reste en stand by. On peut donc l'arrêter avec <CTRL>+C
```
2.
```shell
docker run -d nginx
# 30dfd1b500397ea6b1845ba194f583dd8bae8e55ba828f2ddc2819ede8d7ed00
```
## 4 Cycle de vie des conteneurs
### 4.1.1 Commandes d'observation
```shell
docker ps # conteneurs en cours d'exécution
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 30dfd1b50039 nginx "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp admiring_hermann
docker ps -a # tous les conteneurs
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 30dfd1b50039 nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 80/tcp admiring_hermann
# 5a9d4e300f22 nginx "/docker-entrypoint.…" 4 minutes ago Exited (0) 4 minutes ago infallible_banach
# Pour supprimer toutes les images il faut faire :
docker system prune
```
### 4.1.2 Exercice pratique
1. Créer trois conteneurs nginx avec des noms différents :
```shell
docker run -d --name web1 nginx
# 9de9a334b5001da00fb27ae33e3fc09f4b29a78e9b3606d9cdf61acebaf9941e
docker run -d --name web2 nginx
# db98128c8820faa3720643f7a83d9126a11bf27522a24db7218539023f680a6c
docker run -d --name web3 nginx
# a0d91897890b1eb028571846e5aced4a76bbae8c8c970222a95185b0342e697e
```
2. Les états de chaque conteneurs se remarquent en faisant
3.
```shell
docker ps # Après avoir lancé les conteneurs précédents
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# a0d91897890b nginx "/docker-entrypoint.…" 39 seconds ago Up 38 seconds 80/tcp web3
# db98128c8820 nginx "/docker-entrypoint.…" 52 seconds ago Up 51 seconds 80/tcp web2
# 9de9a334b500 nginx "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp web1
```
## 4.2 Manipulation des états
```shell
docker stop web1
# ça renvoie : web1 et en faisant docker ps, on voit qu'il n'apparait plus.
docker start web1
# ça renvoie : web1
docker restart web2
# Renvoie web2 et en faisant ps on voit que son timer a recommencé
docker pause web3
# renvoie web3 et affiche ceci dans ps : a0d91897890b nginx "/docker-entrypoint.…" 10 minutes ago Up 10 minutes (Paused) 80/tcp web3
docker unpause web3 # le remet à la normal
docker kill web1 # n'apparait plus dans le ps. Et dans ps -a : 9de9a334b500 nginx "/docker-entrypoint.…" 12 minutes ago Exited (137) 28 seconds ago web1
```
# 5 Inspection et Debug
## 5.1 Logs et monitoring
```shell
docker logs [container-name]
# montre les logs de l'image actuelle du container
docker logs -f [container-name]
# montre les logs du container en temps réel
docker stats
# CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
# a0d91897890b web3 0.00% 10.43MiB / 15.42GiB 0.07% 3.15kB / 126B 0B / 12.3kB 13
# db98128c8820 web2 0.00% 10.41MiB / 15.42GiB 0.07% 2.83kB / 126B 0B / 4.1kB 13
# 30dfd1b50039 admiring_hermann 0.00% 10.43MiB / 15.42GiB 0.07% 6.26kB / 126B 0B / 12.3kB 13
```
## 5.2 Inspection détaillée
```shell
docker inspect [container-name]
# "Id": "db98128c8820faa3720643f7a83d9126a11bf27522a24db7218539023f680a6c",
# "Created": "2026-04-13T09:08:18.800415878Z",
# "Path": "/docker-entrypoint.sh",
docker exec -it [container-name] /bin/bash
# renvoie : root@db98128c8820:/# Il permet d'exécuter des commandes dans un container en tant que root
```
# 6 Exercice final
```shell
# 1. Créer un conteneur nginx en mode détaché avec le nom ”web-test”
docker run -d --name web-test nginx
fac3038fbd6c11d119683f146c9be888158e3a145b1ba7050caad8283bb5ac78
docker docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fac3038fbd6c nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 80/tcp web-test
# 2. Pratiquer toutes les commandes du cycle de vie vues précédemment
```shell
[srivasta@salle234-09 TP1]$ docker stop web-test
web-test
[srivasta@salle234-09 TP1]$ docker start web-test
web-test
[srivasta@salle234-09 TP1]$ docker restart web-test
web-test
[srivasta@salle234-09 TP1]$ docker pause web-test
web-test
[srivasta@salle234-09 TP1]$ docker unpause web-test
web-test
[srivasta@salle234-09 TP1]$ docker kill web-test
web-test
```
# 3. Analyser les logs et les différents états
```shell
[srivasta@salle234-09 TP1]$ docker logs web-test
# Le log est TRES long car l'enchainement de start, restart, stop, kill, chaque démarrage ou arrêt, Nginx lance ou coupe des dizaines de sous-processus ("workers"), ce qui génère instantanément une cascade de lignes pour chaque action.
docker inspect web-test
# On voit que ça renvoie un JSON avec l'état actuel (le conteneur est éteint "Status": "exited", "Running": false). Le code d'erreur "ExitCode": 137 indique qu'il a été arrêté brutalement avec le kill que j'ai utilisé. Il est basé sur l'image "nginx", est configuré pour exposer le port "80/tcp".
# 4. Nettoyer lenvironnement (suppression des conteneurs)
docker stop web-test # Il n'apparait donc plus lorsque l'on fait docker ps
```
# 7 Travaux Pratiques Supplémentaires
## 7.1 Rapatrier l'image officielle du serveur web apache (httpd)
```shell
docker pull httpd:alpine3.17
# Digest: sha256:03c154f29d68648c335a19c8bfca1562251bc8af534e10c6f87361551c381d21
# Status: Downloaded newer image for httpd:alpine3.17
# docker.io/library/httpd:alpine3.17
```
## 7.2 Créer un volume
```shell
docker volume create volume_serveur_web #on crée le volume
docker run --rm -v volume_serveur_web:/data alpine sh -c 'echo "<!DOCTYPE html><html><title>C MOI</title><body><h1>Emmanuel</h1></br><p>SRIVASTAVA-TIAMZON</p></body></html>" >> /data/index.html' # On crée le volume qui contient le fichier html demandé.
```
## 7.3 Démarrer un conteneur
```shell
docker run -d --name tp21 httpd # Démarrer un conteneur en mode détaché nommé tp21
docker run -d --name tp22 -v volume_serveur_web:/usr/local/apache2/htdocs/ httpd:alpine3.17 # Démarrer un conteneur en mode détaché en montant le volume précédemment créé nommé tp22
docker run -d --name tp23 -v volume_serveur_web:/usr/local/apache2/htdocs/ -p 8080:80 httpd:alpine3.17 # Démarrer un conteneur en mode détaché en montant le volume précédemment créé et en exposant le port 80 nommé tp23
```
+31
View File
@@ -0,0 +1,31 @@
# 8 Questions de compréhension
1. Quelle est la différence entre une image et un conteneur ?
Un conteneur est un environnement (Linux, web, etc...) qui peut être exécuté, et qui peut exécuter des commandes.
Alors qu'une image est un modèle en lecture seule qui contient des instructions pour créer un conteneur.
On peut prendre des images donc pour créer/modifier un conteneur alors qu'un conteneur est la base d'une image.
2. La différence entre un docker stop et un docker kill :
Le 'docker stop' arrête le conteneur qui est en cours, mais proprement, donc sans répercussion car on ne peut faire de docker stop que dans des cas précis.
Alors qu'un 'docker kill' passe au dessus des cas et des règlementations. Il arrête directement le conteneur mais le fait mal. En vérifiant le log du conteneur suite à un docker kill. On peut voir comment il a mal arrêté les processus et en renvoyant des erreurs.
3. On utilise un mode détaché car lorsque l'on met un conteneur snas mode détaché, il dépend de la machine et donc quand il s'arrête le conteneur s'arrête aussi. Les données enregistrées se perdent donc à la suite. Mettre un conteneur en mode détaché le rend pas dépendant de la machine.
4. Pour vérifier la santé d'un conteneur il faut
Il faut faire docker inspect [container-name] et vérifier le State puis le status pour voir s'il fonctionne et donc qu'il est en bonne santé.
5. Les différents états d'un conteneur sont :
NEW : The task was initialized.
PENDING : Resources for the task were allocated.
ASSIGNED : Docker assigned the task to nodes.
ACCEPTED : The task was accepted by a worker node. If a worker node rejects the task, the state changes to REJECTED.
READY : The worker node is ready to start the task
PREPARING : Docker is preparing the task.
STARTING : Docker is starting the task.
RUNNING : The task is executing.
COMPLETE : The task exited without an error code.
FAILED : The task exited with an error code.
SHUTDOWN : Docker requested the task to shut down.
REJECTED : The worker node rejected the task.
ORPHANED : The node was down for too long.
REMOVE : The task is not terminal but the associated service was removed or scaled down.
+80
View File
@@ -0,0 +1,80 @@
# TP2 : Volumes et bind-mounts
## Exercice 1 : Docker volumes
### Rapatrier limage officielle du serveur web apache (httpd)
```shell
[srivasta@salle234-09 TP2]$ docker pull httpd:alpine3.17
alpine3.17: Pulling from library/httpd
f56be85fc22e: Pull complete
3b0762594298: Pull complete
d57f06c5a70c: Pull complete
add4d5bc8a71: Pull complete
ae430e2a98db: Pull complete
36d8ddf7fbf3: Pull complete
Digest: sha256:03c154f29d68648c335a19c8bfca1562251bc8af534e10c6f87361551c381d21
Status: Downloaded newer image for httpd:alpine3.17
docker.io/library/httpd:alpine3.17
```
### Créer un volume
```shell
docker volume create volume_serveur_web #on crée le volume
docker run --rm -v volume_serveur_web:/data alpine sh -c 'echo "<!DOCTYPE html><html><title>C MOI</title><body><h1>Emmanuel</h1></br><p>SRIVASTAVA-TIAMZON</p></body></html>" >> /data/index.html' # On crée le volume qui contient le fichier html demandé.
docker run -d --name volume_serveur_web_stat -v volume_serveur_web:/usr/local/apache2/htdocs/ -p 6767:80 httpd # On crée le volume temporaire qui prend le volume web et on crée le lien qui va avec en respectant les normes
firefox http://localhost:6767/ # On consulte le fichier index.html
```
![Photo de la page web](image.png)
### Démarrer un conteneur
```shell
docker run -d --name tp21 httpd # Démarrer un conteneur en mode détaché nommé tp21
# 933f36f8b9bb2ebac8e1a909d2174023445d6e38abfacd41cb45effdb4453450
docker run -d --name tp22 -v volume_serveur_web:/usr/local/apache2/htdocs/ httpd:alpine3.17 # Démarrer un conteneur en mode détaché en montant le volume précédemment créé nommé tp22
# 28fa428591cbb76279093082f554753b54d0e7c64491d5d1faceb41c5c9ef598
docker run -d --name tp23 -v volume_serveur_web:/usr/local/apache2/htdocs/ -p 8080:80 httpd:alpine3.17 # Démarrer un conteneur en mode détaché en montant le volume précédemment créé et en exposant le port 80 nommé tp23
# 247b80255b2ac69bdb85f76c4c8b8d2423cacd41a5ebdd8e10c791602ce10841
```
### Exercice complémentaire
Créer un deuxième volume nommé backup_web Copier le contenu du premier volume vers ce nouveau volume Démarrer un conteneur tp24 qui monte les deux volumes simultanément.
```shell
docker volume create backup_web # backup_web
docker run -d --name tp24 -v volume_serveur_web:/usr/local/apache2/htdocs/ -v backup_web:/backup httpd:alpine3.17
# 0622eae7a25de9a2d11456e58f48091eda488d3ca7bce813ee872a2ed4adaaf0
```
## Exercice 2 : Docker bind mounts
Pour cet exercice l'arborescence [web](./web) a été crée avec un [index.html](./web/index.html), un [style.jss](./web/style.css) et un [script.js](./web/script.js).
```shell
# Démarrer un conteneur en mode détaché nommé tp25 qui monte le dossier web local dans /usr/local/apache2/htdocs
docker run -d --name tp25 -v "$PWD"/web/:/usr/local/apache2/htdocs httpd:alpine3.17
# 071b845b325823e3720ab0ec89e42f429d1c9dac928ea342fa425b911603f0cb
# Démarrer un conteneur en mode détaché nommé tp26 qui monte le dossier web et expose le port 8080
docker run -d --name tp26 -v "$PWD"/web/:/usr/local/apache2/htdocs/web/ -p 8080:80 httpd:alpine3.17
# 0fe9b31d025df32c42dea857403952ce988fbc7ac858430e64fb837e8ab2fce4
# Démarrer un conteneur en mode détaché nommé tp27 qui monte uniquement le fichier index.html (et non tout le dossier)
docker run -d --name tp27 -v "$PWD"/web/index.html/:/usr/local/apache2/htdocs/index.html httpd:alpine3.17
# 7b0bad50feff61a4d6dd37c17b7d0f0617ec1837bce88583d0794b3c70414064
```
## Exercice complémentaire
```shell
# 1. Modifier le fichier index.html directement sur votre machine
nano/vim web/index.html # pour apporter une modif
# 2. Vérifier que les changements sont visibles dans le conteneur
docker exec tp26 cat /usr/local/apache2/htdocs/index.html
# 3. Créer un nouveau fichier about.html dans le dossier web
touch /web/about.html
# 4. Vérifier qu'il est automatiquement accessible dans le conteneur
docker exec tp26 ls /web/
```
+34
View File
@@ -0,0 +1,34 @@
# Questions de compréhension
1. Quelle est la différence entre un bind mount et un volume Docker ?
Un bind mount utilise les dossiers de la machine host, tandis qu'un volume est un espace de stockage entièrement géré par Docker.
2. Où sont stockés physiquement les volumes Docker sur votre machine ?
Les volumes Docker sont physiquement stockés dans le répertoire protégé /var/lib/docker/volumes/ (sous Windows et Mac, ils sont cachés dans la machine virtuelle gérée par Docker Desktop).
3. Comment lister les volumes existants ?
Pour lister les volumes existants, utilisez la commande suivante : docker volume ls
4. Comment inspecter le contenu d'un volume ?
On peut inspecter le contenu d'un volume simplement avec : docker volume inspect nom_du_volume
Mais pour voir les fichiers à l'intérieur du volume : docker run --rm -v nom_du_volume:/donnees alpine ls -l /donnees
5. Que se passe-t-il pour les données d'un volume quand on supprime le conteneur associé ?
Un volume est indépendant du cycle de vie du conteneur. Même si on stop ou rm le conteneur, le volume et toutes ses données restent intacts sur la machine jusqu'à ce qu'on décide de supprimer avec la commande docker volume rm nom_du_volume.
# Suite questions de compréhension
6. Quand utiliser un bind mount plutôt qu'un volume Docker ?
On utilise un bind mount pour le développement local afin de voir les modifications de code en temps réel, il faut aussi priviligier un volume pour sauvegarder les données de manière sécurisée en production.
7. Peut-on monter plusieurs dossiers dans un même conteneur ?
Oui, en ajoutant simplement plusieurs options -v dans la commande de démarrage.
8. Quelle est la différence entre monter un dossier et monter un fichier unique ?
Monter un dossier fusionne ou remplace tout le contenu du répertoire cible dans le conteneur, alors que monter un fichier unique ne remplace que ce fichier précis en laissant le reste du dossier intact.
9. Les modifications sont-elles bidirectionnelles avec un bind mount ?
Oui, un changement fait sur la machine se répercute instantanément dans le conteneur, et inversement
10. Comment vérifier les bind mounts actifs sur un conteneur ?
Avec docker inspect nom_du_conteneur il faut examiner la section "Mounts" de la réponse pour lister toutes les liaisons en cours
Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

+10
View File
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Moi</title>
</head>
<body>
<h1>Emmanuel SRIVASTAVA-TIAMZON</h1>
</body>
</html>
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Moi</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Emmanuel SRIVASTAVA-TIAMZON</h1>
<p>Petite modification ! (exo complémentaire)</p>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
alert("Bienvenue");
+3
View File
@@ -0,0 +1,3 @@
h1 {
color: red;
}
+62
View File
@@ -0,0 +1,62 @@
# TP3 : Docker Networks
1. Création des réseaux
```shell
docker network create --driver bridge bridge-tp3 # Création d'un réseau de type bridge.
# c82958e2f11e582accf806f4fe24c35dd652f834e35ce9c975c8ab41057f9eb2
docker network create --driver host host-tp3
docker network create --drive none none-tp3
# Error response from daemon: only one instance of "host" network is allowed : CAR il y a déjà un network host ainsi que none, alors que les dockers network peuvent être crée à volonté.
# En vérifiant avec la commande ci-dessous, on peut vérifier les réseaux dockers déjà instanciés
docker network ls
[srivasta@salle234-09 exo1-networks]$ dar network ls
NETWORK ID NAME DRIVER SCOPE
ad5c5a581e67 bridge bridge local
c82958e2f11e bridge-tp3 bridge local
55ace904f2d5 host host local
59c5b3091f5b none null local
```
2. Création des conteneurs
```shell
# De notre côté on crée des dossiers web1,2,3 et met un index.html dans chacun d'entre eux.
# Ensuite on lances les conteneurs web1 et web2 en montant le fichier index.html à l'emplacement demandé.
docker run -d --name web1 --network bridge-tp3 -v "$PWD"/web1/index.html:/usr/share/nginx/html/index.html nginx:alpine
# docker run -d --name web1 --network bridge-tp3 -v "$PWD"/web1/index.html:/usr/share/nginx/html/index.html nginx:alpine web1 sur bridge-tp3
docker run -d --name web2 --network bridge-tp3 -v "$PWD"/web2/index.html:/usr/share/nginx/html/index.html nginx:alpine
# 9dd106f74be931c67d7a29efc25eb4cbcc64da8826773a9100cd244220d94d83 web2 sur bridge-tp3
docker run -d --name web3 --network host -v "$PWD"/web3/index.html:/usr/share/nginx/html/index.html nginx:alpine
# 4fd0e8ba56605f04722e99ffe34d70329dbd69bcf455b80bf00f087e6ee8f523
docker run -d --name web4 --network none -v "$PWD"/web4/index.html:/usr/share/nginx/html/index.html nginx:alpine
# 5bc61fee7ca46a1bba6a3738611d2f53ae3e19cfe8af0b386ce2dff8efab13a4
```
3. Tests de communication
```shell
# Test ping entre web1 et web2
[srivasta@salle234-09 exo1-networks]$ docker exec web1 ping web2
PING web2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.052 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.038 ms
^C
# Test ping entre web1 et web3
[srivasta@salle234-09 exo1-networks]$ dar exec web1 ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1): 56 data bytes
64 bytes from 172.17.0.1: seq=0 ttl=64 time=0.053 ms
64 bytes from 172.17.0.1: seq=1 ttl=64 time=0.179 ms
^C
#Test ping entre web1 et web4 Ping impossible car inatteignable
[srivasta@salle234-09 exo1-networks]$ dar exec web1 ping web4
ping: bad address 'web4'
```
* L'adresse du conteneur web1 : http://172.18.0.2/ En allant sur firefox, la fenêtre s'affiche bien
* web2 : http://172.18.0.3/
* web3 : http://172.17.0.1/
* web4 n'a pas d'adresse ip qui lui est propre car c'est un none.
+24
View File
@@ -0,0 +1,24 @@
## 1. Création des réseaux
* bridge-tp3 : La création a réussi. Docker permet de créer plusieurs réseaux de type "bridge" personnalisés pour isoler des groupes de conteneurs.
* host-tp3 & none-tp3 : La création a échoué car Docker n'autorise qu'une seule instance des drivers "host" et "none". Ces réseaux existent déjà par défaut lors de l'installation de Docker.
## 2. Tests de communication
* web1 vers web2 : Réussi.
* Sur un réseau bridge personnalisé, Docker active un service DNS interne. Il permet aux conteneurs de communiquer entre eux en utilisant leurs noms au lieu de leurs adresses IP ce qui nous facilite la tâche.
* web1 vers web3 : Réussi (via l'IP 172.17.0.1).
* Le conteneur web3 utilise le réseau host. On peut donc le joindre avec l'adresse IP de la passerelle (gateway) qui relie le bridge de l'hôte au système.
* web1 vers web4 : Échec ("bad address").
* Le conteneur web4 est configuré avec le driver "none". Il ne possède aucune interface réseau externe ni adresse IP, ce qui le rend totalement isolé et inatteignable par le réseau comme dit dans le cours.
## 3. Accès HTTP et vérification du contenu
* web1 (172.18.0.2) & web2 (172.18.0.3) : Les pages sont accessibles avec le navigateur. Le montage de volume (`-v`) a correctement remplacé le fichier par défaut de Nginx par notre `index.html`.
* web3 (172.17.0.1) : La page s'affiche correctement. En mode host, le serveur Nginx écoute directement sur les interfaces réseau de la machine hôte.
* web4 : Aucun accès possible. Comme il n'a pas d'adresse IP, aucun flux HTTP ne peut aller vers ce conteneur.
![Image du containeur web 1](./container_web1.png)
![Image du containeur web 2](./container_web2.png)
![Image du containeur web 3](./container_web3.png)
![Image du containeur web 4](./container_web4.png)
Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Container Info</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #f0f2f5;
}
.container {
text-align: center;
padding: 20px;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 {
color: #2496ed;
margin-bottom: 20px;
}
h2 {
color: #384c54;
}
</style>
</head>
<body>
<div class="container">
<h1>Container: web1</h1>
<h2>Date et heure: <span id="datetime"></span></h2>
</div>
<script>
function updateDateTime() {
const now = new Date();
const options = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
};
document.getElementById('datetime').textContent =
now.toLocaleDateString('fr-FR', options);
}
// Mise à jour initiale
updateDateTime();
// Mise à jour toutes les secondes
setInterval(updateDateTime, 1000);
</script>
</body>
</html>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Container Info</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #f0f2f5;
}
.container {
text-align: center;
padding: 20px;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 {
color: #2496ed;
margin-bottom: 20px;
}
h2 {
color: #384c54;
}
</style>
</head>
<body>
<div class="container">
<h1>Container: web2</h1>
<h2>Date et heure: <span id="datetime"></span></h2>
</div>
<script>
function updateDateTime() {
const now = new Date();
const options = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
};
document.getElementById('datetime').textContent =
now.toLocaleDateString('fr-FR', options);
}
// Mise à jour initiale
updateDateTime();
// Mise à jour toutes les secondes
setInterval(updateDateTime, 1000);
</script>
</body>
</html>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Container Info</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #f0f2f5;
}
.container {
text-align: center;
padding: 20px;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 {
color: #2496ed;
margin-bottom: 20px;
}
h2 {
color: #384c54;
}
</style>
</head>
<body>
<div class="container">
<h1>Container: web3</h1>
<h2>Date et heure: <span id="datetime"></span></h2>
</div>
<script>
function updateDateTime() {
const now = new Date();
const options = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
};
document.getElementById('datetime').textContent =
now.toLocaleDateString('fr-FR', options);
}
// Mise à jour initiale
updateDateTime();
// Mise à jour toutes les secondes
setInterval(updateDateTime, 1000);
</script>
</body>
</html>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Container Info</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #f0f2f5;
}
.container {
text-align: center;
padding: 20px;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 {
color: #2496ed;
margin-bottom: 20px;
}
h2 {
color: #384c54;
}
</style>
</head>
<body>
<div class="container">
<h1>Container: web4</h1>
<h2>Date et heure: <span id="datetime"></span></h2>
</div>
<script>
function updateDateTime() {
const now = new Date();
const options = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
};
document.getElementById('datetime').textContent =
now.toLocaleDateString('fr-FR', options);
}
// Mise à jour initiale
updateDateTime();
// Mise à jour toutes les secondes
setInterval(updateDateTime, 1000);
</script>
</body>
</html>
@@ -0,0 +1,9 @@
# TP 3 : Dockerfile
## Actions à réaliser
### 1. Création du Dockerfile
```Dockerfile
FROM alpine:3.23 AS DF
RUN apt install apache2
LABEL maintainer="srivastava" version="1.8" TP="3"
```
+23
View File
@@ -0,0 +1,23 @@
FROM alpine:3.23
RUN apk add apache2
LABEL MAINTAINER="srivastava" VERSION="1.8" TP="3"
# Ajout de métadonnées pour le mainteneur, la version et le numéro du TP
ENV SCHOOL="IUT" LEVEL="1.8"
# Définition de variables d environnement pour l école et le niveau
EXPOSE 80
# Exposition du port 80 pour le serveur web
RUN apk add git && git clone https://github.com/MaximePIERRONT/beforeStage.git /tmp/repo && cp /tmp/repo/static-site.html /var/www/localhost/htdocs/static-site.html && rm -rf /tmp/repo && apk del git
# Installation de git, clonage du dépôt, copie du fichier HTML dans le répertoire de l hôte web, suppression du dépôt et désinstallation de git
RUN sed -i 's/NOM PRENOM/SRIVASTAVA Emmanuel/g' /var/www/localhost/htdocs/static-site.html
# Modification du fichier HTML pour remplacer "NOM PRENOM" par "SRIVASTAVA Emmanuel"
HEALTHCHECK --interval=1m --timeout=1s CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
# Commande pour démarrer le serveur Apache en mode premier plan
Binary file not shown.
+59
View File
@@ -0,0 +1,59 @@
import { useState, useEffect } from 'react';
const HealthCheck = () => {
const [status, setStatus] = useState<'loading' | 'online' | 'offline'>('loading');
useEffect(() => {
const checkHealth = async () => {
try {
const response = await fetch('/api/health');
const data = await response.json();
setStatus(data.status === 'ok' ? 'online' : 'offline');
} catch (error) {
setStatus('offline');
}
};
checkHealth();
const interval = setInterval(checkHealth, 30000);
return () => clearInterval(interval);
}, []);
const getStatusStyles = () => {
switch (status) {
case 'online':
return { backgroundColor: '#deffde', padding: '1rem', borderRadius: '4px' };
case 'offline':
return { backgroundColor: '#ffeded', padding: '1rem', borderRadius: '4px' };
default:
return { backgroundColor: '#f3f3f3', padding: '1rem', borderRadius: '4px' };
}
};
const getStatusMessage = () => {
switch (status) {
case 'online':
return '✅ Le backend est accessible et fonctionne correctement';
case 'offline':
return '❌ Le backend n\'est pas accessible';
default:
return '⏳ Vérification de la connexion avec le backend...';
}
};
return (
<div style={{ padding: '1rem' }}>
<div style={getStatusStyles()}>
{status === 'loading' && (
<span style={{ display: 'inline-block', animation: 'spin 1s linear infinite' }}>🔄</span>
)}
<span style={{ marginLeft: status === 'loading' ? '8px' : '0' }}>
{getStatusMessage()}
</span>
</div>
</div>
);
};
export default HealthCheck;
@@ -0,0 +1,6 @@
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
+19
View File
@@ -0,0 +1,19 @@
from fastapi import FastAPI
from pymongo import MongoClient
app = FastAPI()
# MongoDB connection
client = MongoClient("mongodb://mongodb:27017/")
db = client.memes_db
@app.get("/memes")
def get_memes():
memes = list(db.memes.find({}, {"_id": 0}))
return {"memes": memes}
@app.post("/memes")
def create_meme(title: str, url: str):
meme = {"title": title, "url": url}
db.memes.insert_one(meme)
return {"message": "Meme added successfully"}
@@ -0,0 +1,5 @@
fastapi==0.68.0
uvicorn[standard]==0.15.0
python-multipart
pymongo==3.12.0
websockets==10.0
@@ -0,0 +1,34 @@
version: '3.8'
services:
mongodb:
image: mongodb/mongodb-atlas-local
volumes:
- mongodb_data:/data/db
networks:
- backend-network
restart: always
backend:
build: ./backend
depends_on:
- mongodb
networks:
- backend-network
- frontend-network
frontend:
build: ./frontend
ports:
- "80:80"
networks:
- frontend-network
depends_on:
- backend
volumes:
mongodb_data:
networks:
backend-network:
internal: true
frontend-network:
@@ -0,0 +1,3 @@
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
COPY nginx.conf /etc/nginx/conf.d/default.conf
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head>
<title>Meme Gallery</title>
<style>
.meme { margin: 10px; padding: 10px; border: 1px solid #ccc; }
</style>
</head>
<body>
<h1>Meme Gallery</h1>
<div>
<h2>Add a Meme</h2>
<input type="text" id="title" placeholder="Title">
<input type="text" id="url" placeholder="Image URL">
<button onclick="addMeme()">Add Meme</button>
</div>
<div id="memes"></div>
<script>
async function loadMemes() {
const response = await fetch('/backend/memes');
const data = await response.json();
const memesDiv = document.getElementById('memes');
memesDiv.innerHTML = data.memes.map(meme => `
<div class="meme">
<h3>${meme.title}</h3>
<img src="${meme.url}" width="200">
</div>
`).join('');
}
async function addMeme() {
const title = document.getElementById('title').value;
const url = document.getElementById('url').value;
await fetch('/backend/memes?' + new URLSearchParams({
title: title,
url: url
}), {method: 'POST'});
loadMemes();
}
loadMemes();
</script>
</body>
</html>
@@ -0,0 +1,18 @@
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /backend/ {
proxy_pass http://backend:8000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
+105
View File
@@ -0,0 +1,105 @@
# Docker Compose - Aide-mémoire
## Commandes Essentielles
### Démarrage et Arrêt
```bash
# Démarrer les services
docker compose up -d # Mode détaché (arrière-plan)
docker compose up # Mode interactif (voir les logs)
# Arrêter les services
docker compose down # Arrête et supprime les conteneurs
docker compose stop # Arrête sans supprimer
```
### Logs et Surveillance
```bash
# Voir les logs
docker compose logs # Tous les logs
docker compose logs -f # Suivre les logs en direct
docker compose logs [service] # Logs d'un service spécifique
# État des conteneurs
docker compose ps # Liste et état des conteneurs
```
### Construction et Reconstruction
```bash
# Construire les images
docker compose build # Tous les services
docker compose build [service] # Un service spécifique
# Reconstruction et démarrage
docker compose up -d --build # Reconstruire puis démarrer
```
## Structure docker-compose.yml
### Services
```yaml
services:
monservice:
image: ... # Utiliser une image existante
build: ... # Construire depuis un Dockerfile
ports: # Exposer des ports
volumes: # Monter des volumes
depends_on: # Définir des dépendances
networks: # Connecter aux réseaux
```
### Réseaux
```yaml
networks:
monreseau: # Réseau simple
monreseau_interne:
internal: true # Réseau isolé
```
### Volumes
```yaml
volumes:
monvolume: # Volume pour persistance
```
## Commandes Utiles
### Inspection
```bash
# Vérifier la configuration
docker compose config # Valider le fichier compose
# Voir les réseaux
docker network ls # Lister les réseaux
docker network inspect [réseau] # Détails d'un réseau
# Voir les volumes
docker volume ls # Lister les volumes
```
### Debug
```bash
# Accéder à un conteneur
docker compose exec [service] sh # Ouvrir un shell
# Voir les processus
docker compose top # Processus en cours
```
### Gestion des Services
```bash
# Redémarrer des services
docker compose restart # Tous les services
docker compose restart [service] # Un service spécifique
# Recréer des conteneurs
docker compose up -d --force-recreate
```
## Conseils
- Utilisez toujours `-d` en production, jamais en développement
- Pensez à vérifier les logs en cas de problème
- `docker compose config` est votre ami pour valider la syntaxe
- Les réseaux se créent automatiquement
- Les volumes persistent après un `down` (sauf si `-v`)
+205
View File
@@ -0,0 +1,205 @@
# TP4 Docker Compose - Application de Mèmes
### Objectif
Créer une application web de partage de mèmes en utilisant Docker Compose pour orchestrer 3 conteneurs :
- Un frontend (nginx)
- Un backend (Python/FastAPI)
- Une base de données (MongoDB)
### Prérequis
- Docker et Docker Compose installés
- Un éditeur de code (VS Code recommandé)
### Structure du projet
```
meme-app/
├── backend/
│ ├── Dockerfile
│ ├── requirements.txt
│ └── app.py
├── frontend/
│ ├── Dockerfile
│ ├── nginx.conf
│ └── index.html
└── docker-compose.yml
```
### Étape 1 : Mise en place de la structure (5 min)
```bash
# Créer l'arborescence
mkdir meme-app
cd meme-app
mkdir backend frontend
touch docker-compose.yml
```
### Étape 2 : Backend (20 min)
1. Créer backend/requirements.txt :
```
fastapi==0.68.0
uvicorn[standard]==0.15.0
python-multipart
pymongo==3.12.0
websockets==10.0
```
2. Créer backend/app.py :
```python
from fastapi import FastAPI
from pymongo import MongoClient
app = FastAPI()
# MongoDB connection
client = MongoClient("mongodb://mongodb:27017/")
db = client.memes_db
@app.get("/memes")
def get_memes():
memes = list(db.memes.find({}, {"_id": 0}))
return {"memes": memes}
@app.post("/memes")
def create_meme(title: str, url: str):
meme = {"title": title, "url": url}
db.memes.insert_one(meme)
return {"message": "Meme added successfully"}
```
3. Créer backend/Dockerfile :
```dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
```
### Étape 3 : Frontend (20 min)
1. Créer frontend/index.html :
```html
<!DOCTYPE html>
<html>
<head>
<title>Meme Gallery</title>
<style>
.meme { margin: 10px; padding: 10px; border: 1px solid #ccc; }
</style>
</head>
<body>
<h1>Meme Gallery</h1>
<div>
<h2>Add a Meme</h2>
<input type="text" id="title" placeholder="Title">
<input type="text" id="url" placeholder="Image URL">
<button onclick="addMeme()">Add Meme</button>
</div>
<div id="memes"></div>
<script>
async function loadMemes() {
const response = await fetch('/backend/memes');
const data = await response.json();
const memesDiv = document.getElementById('memes');
memesDiv.innerHTML = data.memes.map(meme => `
<div class="meme">
<h3>${meme.title}</h3>
<img src="${meme.url}" width="200">
</div>
`).join('');
}
async function addMeme() {
const title = document.getElementById('title').value;
const url = document.getElementById('url').value;
await fetch('/backend/memes?' + new URLSearchParams({
title: title,
url: url
}), {method: 'POST'});
loadMemes();
}
loadMemes();
</script>
</body>
</html>
```
2. Créer frontend/nginx.conf :
```nginx
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /backend/ {
proxy_pass http://backend:8000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
3. Créer frontend/Dockerfile :
```dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
COPY nginx.conf /etc/nginx/conf.d/default.conf
```
### Étape 4 : Docker Compose (45 min)
Votre mission : Créer le fichier docker-compose.yml pour :
1. Démarrer MongoDB
2. Démarrer le backend Python en le connectant à MongoDB
3. Démarrer le frontend Nginx en le connectant au backend
4. Gérer les réseaux pour isoler MongoDB
5. Configurer un volume pour les données MongoDB
Points à considérer :
- Quels services doivent communiquer entre eux ?
- Quels ports doivent être exposés ?
- Comment assurer la persistance des données ?
- Dans quel ordre les services doivent-ils démarrer ?
### Étape 5 : Tests (30 min)
1. Démarrer l'application :
```bash
docker compose up -d
```
2. Vérifier que tout fonctionne :
- Ouvrir http://localhost dans le navigateur
- Ajouter un mème (utilisez une URL d'image depuis le web)
- Vérifier qu'il s'affiche dans la galerie
3. Tester la persistance :
```bash
docker compose down
docker compose up -d
```
Les mèmes doivent toujours être là !
### Rendu attendu
- Le fichier docker-compose.yml complet et fonctionnel
- Une explication de vos choix de configuration
- Un exemple de mème ajouté via l'interface
### Pour aller plus loin
- Ajoutez des variables d'environnement pour la configuration
- Implémentez un healthcheck pour MongoDB
- Configurez un backup automatique de la base de données