TP1 Part 2 : Dev environment¶
Dans cette partie, on va setup ce qu'on appelle "un environnement de dév Docker" : mettre le code d'une app dans un conteneur, et éventuellement tout ce dont elle a besoin dans des conteneurs aussi.
1. Introoo¶
D'abord, on va fabriquer notre conteneur qui va contenir notre application.
J'ai codé une app toute pourrie en Node pour illustrer cette partie. Vous la trouverez ici.
Dans la partie précédente, on a fait que se servir d'images officielles existantes : mysql:8.4 et phpmyadmin:latest.
Ici, pour faire les choses clean, on va fabriquer nous-mĂȘmes notre image.
Pour fabriquer une image, il faut :
- écrire un
Dockerfile - lancer la commande
docker buildpour produire l'image Ă partir duDockerfile
Pour la construction de notre Dockerfile, on va :
- partir d'une image officielle
node - installer nos dépendances (mon app a juste besoin de Express)
- définir la commande à lancer lorsqu'on
docker runnotre image
Let's goooo.
2. Dockerfile¶
â Dans votre dĂ©pĂŽt git de rendu, crĂ©er un nouveau sous-dossier
- appelez-le
part2/1/
đ RĂ©cupĂ©rez le package.json et app.js que je vous ai cook
-
déposez les fichiers comme suit :
part2/1/package.jsonpart2/1/src/app.js
đ Ajoutez un fichier part2/1/Dockerfile avec le contenu suivant :
# On part de l'image officielle node
FROM node
# On exécute des commandes mkdir pour préparer les dossiers qui vont accueillir notre code
RUN mkdir /app && mkdir /app/src
# On définit /app comme le "WORKDIR"
# A partir de cette ligne, toutes les commandes sont relatives au dossier /app
WORKDIR /app
# Copie du fichier package.json (de votre machine) dans le dossier "."
# "." fait référence au dossier actuel, qui est notre WORKDIR (donc c'est /app)
COPY ./package.json .
# Installation des dépendances
# Grùce à notre WORKDIR, cette commande est effectuée depuis le dossier /app de l'image
RUN npm install
# On copie le reste du code dans l'image
COPY ./src ./src
# On définit la commande à lancer lorsque le conteneur démarre
# Notez la syntaxe reloue (mais trĂšs secure) : sous forme de liste, pas d'espace
CMD [ "npm", "run", "dev" ]
đ Construire l'image shitty_app Ă partir de ce Dockerfile :
- toujours depuis un shell, déplacez vous dans le dossier qui contient ce
Dockerfile - exécutez la commande
docker buildsuivante :
# Déplacez vous dans le dossier qui contient vos fichiers
⯠cd part2/1
# Vous devriez avoir ça :
⯠tree -L2
.
âââ Dockerfile
âââ package.json
âââ src
âââ app.js
# -t comme tag : on indique le nom de notre image (on la "tag")
# le "." c'est pour indiquer le chemin vers le "contexte de build" : lĂ oĂč on trouve le Dockerfile notamment
⯠docker build -t shitty_app:1.0 .
[...]
Hint
Toujours : se déplacer dans le dossier qui contient le Dockerfile pour build (c'est le plus simple).
Info
Ici l'image s'appelle shitty_app et son tag c'est 1.0. Souvent on se sert du tag pour indiquer la version du programme.
Quand tu vas sur un README.md bien foutu du Hub, tu peux voir tous les tags disponibles pour une image donnée : https://hub.docker.com/_/python
Dans la vraie vie, on tag TOUJOURS les images explicitement, et on utilise jamais latest en production : on veut "pin" les versions : préciser explicitement quelle version on souhaite utiliser.

đ Lancer l'application avec une commande docker run, cette commande :
- lance l'image
shitty_app - utilise option
-ppour partager le port3000et ainsi accéder à l'interface web - utilise option
-dpour mettre en fond
đ Prouvez que ça tourne, dans le compte-rendu, vous me mettez :
- un
docker psqui montre que le conteneur est actif - un
docker logsqui montre les logs du programme (on doit voir qu'il tourne sur le port3000) - un
curlvers la WebUI
3. Hot reload pleaaaase¶
A. Intro¶
Note
La lib nodemon déclarée dans le package.json va nous permettre de supporter le hot-reload.
Ok c'est cool tout est conteneurisé, mais grave chiant si on doit relancer docker build à chaque fois qu'on modifie le code.
Bah ouais, actuellement, le code est dans l'image : c'est dans le Dockerfile avec un COPY qu'on met notre app.js.
â Pour avoir l'environnement idĂ©al, on veut :
- lancer notre conteneur
- coder sur notre PC avec notre IDE de fouuu
- que ça modifie en temps réel le code dans le conteneur qui tourne
- que la page qui soit served soit mise Ă jour si on actualise
Hot reload quoi !
â Pour ça, on va utiliser les volumes Docker qui permettent exactement ça :
- partager un dossier (ou un fichier) de notre PC au conteneur
- on le fait au moment du
docker run(pas dans leDockerfile) - le dossier est partagé en temps réel avec le conteneur pendant que le conteneur vit
B. Do it¶
đ Lancer un nouveau conteneur Ă partir de l'image shitty_app
- cette fois, vous ajoutez une option
-vpour utiliser un volume - l'option
-vdoit partager le dossiersrc/qui contient monapp.jsde votre PC vers le dossier/app/src/dans le conteneur - ça va donner un truc du genre :
đ VĂ©rifier que ça fonctionne
- modifier le fichier
app.jsdepuis votre PC (ajoutez un machin dans l'contenu HTML qui soit visible facilement sur un refresh) - vérifier que votre modif est visible en visitant la WebUI
- pour le compte-rendu, je veux un
docker logssur votre conteneur : avec la libnodemonil log quand il effectue un hot-reload (il détecte la modification de fichiers)
4. Compose please¶
đ Transformer ce docker run en compose.yml
- tout est dit : ajoutez un fichier
compose.ymlà cÎté duDockerfile - il lance
shitty_appavec toutes nos ptites options (partage de ports + volume)
Note
On commence à s'approcher d'un truc vraiment clean et pratique là : tu veux dév ? Tu fais juste un docker compose up et go.
Aucune dépendance installée sur la machine.
Partage d'environnement super facile : suffit de partager le Dockerfile et le compose.yml deux simples fichiers texte, y'a tout dedans.
Et ca s'executera exactement pareil ailleurs.

5. DB please¶
A. Ptite intro¶
On finit ce TP avec l'ajout d'une DB MySQL à cÎté d'une app Node, histoire d'avoir une stack un peu complÚte.
Au menu :
- je vous file un nouveau
app.js - vous construisez une nouvelle image
shitty_app_with_db - vous écrivez un
compose.ymlqui lance : une DB, un PHPMyAdmin, lashitty_app_with_db
On fait ça clean :
- du hot-reload (donc vous définissez un volume dans le
compose.yml) - mon app attend les infos de connexions à la base en variable d'environnement, il faudra les définir dans le
compose.yml
B. Feu¶
â Dans votre dĂ©pĂŽt git de rendu, crĂ©er un nouveau sous-dossier
- appelez-le
part2/5/
đ RĂ©cupĂ©rer la nouvelle app
Note
Respectez la mĂȘme structure qu'avant : avec le sous-dossier src/ qui contient app.js.
đ CrĂ©er un Dockerfile
- dans
part2/5/Dockerfilepour le dĂ©pĂŽt git de rendu - le mĂȘme
Dockerfilequ'avant ça fait l'affaire nickel
đ CrĂ©er un compose.yml
- récupérez celui de la partie 1 et celui de la partie 2 : fusioooon
-
ce
compose.ymldoit déclarer trois conteneurs :-
une DB MySQL en 8.4
- déclarée avec le nom
db
- déclarée avec le nom
-
un PHPMyAdmin
- partage de ports pour accéder à l'interface
-
la
shitty_app_with_dbaccessible sur votre port3000- partage de ports pour accéder à l'interface
- volume qui partage le fichier
app.jspour supporter le hot-reload - variables d'environnement pour donner les infos de connexion Ă la db (voir la section "Info" juste en dessous)
-
Info
Les variables à déclarer sont les classiques hein : adresse IP de la base, le port, nom du user et password pour se connecter, nom de la database.
Ca donne donc une section environment comme ça avec les variables que j'utilise dans le code :
environment:
- DB_HOST=db # en supposant que vous avez bien déclaré votre conteneur MySQL avec le nom "db"
- DB_USER=root
- DB_PASSWORD=<TON_PASSWORD>
- DB_NAME=<NOM_DE_DB>
- DB_PORT=3306
- PORT=3000
<TON_PASSWORD> par la mĂȘme valeur que le MYSQL_ROOT_PASSWORD du conteneur MySQL.Et aussi remplacer
<NOM_DE_DB> par un nom de votre choix : la database est créée par app.js quand le programme démarre :)
â Vous devriez donc avoir quelque chose comme :
⯠cd part2/5
⯠tree -L2
.
âââ compose.yml
âââ Dockerfile
âââ package.json
âââ src
âââ app.js
2 directories, 4 files
đ Allumer la stack et prouver que ça fonctionne
docker compose up! (depuis le dossierpart2/5/)- visitez l'interface :
http://localhost:3000 -
pour le compte-rendu, je veux :
- un
docker psqui montre les conteneurs actifs - un
docker compose logsqui montre les logs de nos 3 conteneurs - un
curlvers la WebUI de PHPMyAdmin - un
curlvers la WebUI de lashitty_app_with_db
- un
C. DonnĂ©es persistentes¶
Haaaaa avant de partir. Si on supprime la DB on perd toutes les data lĂ .
Info
Quand vous faites un docker compose down ça supprime les conteneurs.
C'est ce que vous voulez : les conteneurs permettent une approche "lancer, détruire, relancer".
Et c'est désirable : t'as pas un truc qui marche mais tu sais plus trop comment.
Là c'est reproductible et maßtrisé.
Ca serait bien de pouvoir conserver les datas, mĂȘme si notre conteneur de db il meurt ou est supprimĂ©.
L'idée est simple : on utilise un volume pour que le conteneur stocke en réalité les données de db sur notre machine hÎte.
đ Mettre en place des donnĂ©es persistentes pour la db
- il faut ajouter un
volumeaucompose.ymlpour le conteneurdb - lisez le
README.mdde l'image MySQL officielle, c'est clairement indiqué quel volume faire
T'as fini le TP je crois, gg :d
Oublie pas de m'envoyer le lien vers ton repo git par Discord đ