[TOC] # Question 3 ![image](https://hackmd.io/_uploads/B1XWh_ko6.png) ## Installation de Docker Engine sur Ubuntu (via les `apt repository`) Source : [Install Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/) Dans le cadre de ce TP, l'environement hôte utilisé sera **WSL** : ```BASH # Add Docker's official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to Apt sources: echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update ``` Puis installer docker : ```BASH sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ``` Le démon docker doit être lancé à chaque démarrage de WSL : `sudo service docker start` ![image](https://hackmd.io/_uploads/BJS50u1j6.png) L'image Docker décrite par le dockerfile doit être buildée via la commande : ```BASH sudo docker build -t "<tag/nom de l'image>" . ``` ![image](https://hackmd.io/_uploads/H1FRxKyj6.png) Un conteneur Docker peut ensuite être construit et lancé depuis cette image par la commande : ```BASH sudo docker run -p <port hôte>:<port containeur> "<tag/nom de l'image>" ``` - L'option `-p` permet d'associer un port de l'environement conteneurisé à un port du système hôte. On parle de "***published ports***" - L'option `-d` passée à la commande `docker run` permet d'executer le conteneur Docker en arrière plan. ## Base de données MongoDB ![image](https://hackmd.io/_uploads/rkj_pO1jp.png) Je récupère l'image de mongoDB sur Docker via cette commande : ```sudo docker pull mongo``` Je peux vérifier la bonne récupération de l'image en listant les images stockées en local : ```BASH sudo docker image ls ``` ![image](https://hackmd.io/_uploads/H1u4fY1oT.png) Lancement de la base de données avec la commande : ```BASH sudo docker run --name mongodb -v ~/mongo/data:/data/db -p 27018:27017 mongo ``` Je peux voir avec ``localhost:27018`` que la base est bien montée. :::info L'option et l'argument `-v ~/mongo/data:/data/db` permet de faire pointer le répertoire `/data/db` interne au conteneur pointe vers le répertoire `~/mongo/data` de la machine hôte par l'intermediaire du système des volumes Docker. De cette manière, bien qu'elle soit lancée au sein d'un conteneur Docker, les données de la base Mongo DB sont stockées de manière persistente sur le disque dur de la machine hôte. ::: PS : Pour supprimer un conteneur déjà existant : ```BASH sudo docker rmi -f <image_id> ``` :::info Par exemple ici : `sudo docker rmi -f 50de30b43cad` ::: Ou si l'erreur est la suivante : Lancer la commande : ```BASH sudo docker rm 575fefec61260515073d8a9d4e0d616425920d4d6234291a2e9859ad71cc905c ``` ## Service `calories` ![image](https://hackmd.io/_uploads/Syf1oYJoT.png) L'image de l'API `calories` est construite par le `dockerfile` suivant : ```dockerfile FROM node:20-alpine # Image de base : node 20 # Définition des variables d'environnement ENV MONGODB_CONNECTION_STRING=mongodb://172.17.0.1:27018/calories_database ENV MONGODB_COLLECTION=calories_collection # Définition du répertoire de travail WORKDIR /calories_app # Copie des fichiers du repertoire au sein du conteneur COPY . /calories_app # Installation des dépendances listées dans le fichier 'package.json' RUN npm install # Commande executée au lancement du conteneur CMD ["node", "app.js"] ``` - La variable d'environement `MONGODB_CONNECTION_STRING` contient la **`connection string`** (i.e. l'adresse) vers la base de données Mongo DB contenant les données nutritionnelles - La variable d'environement `MONGODB_COLLECTION` contient le nom de la collection (i.e. la table dans le modèle relationnel) où sont stockées les données nutritionnelles :::info En Ruby, les paquets dont dépend l'application sont listées avec leurs version dans un fichier `json` nommé `package.json` : ![image](https://hackmd.io/_uploads/BJip6ne66.png) ::: :::warning Sous les version Unix de Docker, les conteneurs construits sont par défaut ajouté à l'adapter réseau `bridge`. Ce dernier associe l'adresse de la machine hôte (`localhost`) à `172.17.0.1`. Nous utilisons ainsi cette adresse afin de contacter d'autre conteneurs Docker lancés sur la machine hôte ::: ### Lancement du service Déplacement dans le répertoire : ```BASH cd calories ``` Construction de l'image Docker depuis le `dockerfile` : ```BASH sudo docker build -t vm_docker_tp2-calories . ``` Construction et lancement d'un conteneur Docker basé sur l'image `vm_docker_tp2-calories` : ```BASH sudo docker run -p 5004:80 vm_docker_tp2-calories ``` Le service peut ensuite être accedé par navigateur à l'adresse `http://localhost:5004/` ## Service `ingredients` ![image](https://hackmd.io/_uploads/BJCBVngap.png) L'image de l'API `ingredients` est construite par le `dockerfile` suivant : ```dockerfile= FROM ruby:2.7.1 # Image de base : Ruby 2.7.1 # Définition du répertoire de travail WORKDIR /ingredient_app # Copie des fichiers du repertoire au sein du conteneur COPY . /ingredient_app # Installation des dépendances (i.e. Gems) listées dans le Gemfile RUN bundle install # Commande executée au lancement du conteneur CMD ["ruby", "ingredients.rb"] ``` :::info En Ruby, les Gems dont dépend l'application sont listées avec leurs version dans un `Gemfile` ![image](https://hackmd.io/_uploads/rk-BhneTa.png) ::: ### Lancement du service Déplacement dans le répertoire : ```BASH cd ingredients ``` Construction de l'image Docker depuis le `dockerfile` : ```BASH sudo docker build -t vm_docker_tp2-ingredients . ``` Construction et lancement d'un conteneur Docker basé sur l'image `vm_docker_tp2-ingredients` : ```BASH sudo docker run -p 5001:80 vm_docker_tp2-ingredients ``` Le service peut ensuite être accedé par navigateur à l'adresse `http://localhost:5001/` ## Service `recipes` ![image](https://hackmd.io/_uploads/rkjq-hlpT.png) L'image de l'API `recipes` est construite par le `dockerfile` suivant : ```dockerfile FROM python:3.12-alpine # Image de base : Python 3.12 # Définition des variables d'environnement ENV INGREDIENTS_API_URL=http://172.17.0.1:5001 # Définition du répertoire de travail WORKDIR /recipes_api_app # Copie des fichiers du repertoire au sein du conteneur COPY . . # Installation des dépendances RUN pip install -r requirements.txt # Commande executée au lancement du conteneur CMD ["python3", "main.py", "5000"] ``` - La variable d'environement `INGREDIENTS_API_URL` contient l'adresse vers l'API des ingrédients :::warning Sous les version Unix de Docker, les conteneurs construits sont par défaut ajouté à l'adapter réseau `bridge`. Ce dernier associe l'adresse de la machine hôte (`localhost`) à `172.17.0.1`. Nous utilisons ainsi cette adresse afin de contacter d'autre conteneurs Docker lancés sur la machine hôte ::: ### Lancement du service Déplacement dans le repertoire : ```BASH cd recipes ``` Construction de l'image Docker depuis le `dockerfile` : ```BASH sudo docker build -t vm_docker_tp2-recipes . ``` Construction et lancement d'un conteneur Docker basé sur l'image `vm_docker_tp2-recipes` : ```BASH sudo docker run -p 5002:5000 vm_docker_tp2-recipes ``` Le service peut ensuite être accedé par navigateur à l'adresse `http://localhost:5002/` ## Service `website` ![image](https://hackmd.io/_uploads/r16octko6.png) ![image](https://hackmd.io/_uploads/rkC29Kyjp.png) L'image du site web est construite par le `dockerfile` suivant : ```dockerfile FROM python:3.12-alpine # Image de base : Python 3.12 # Définition des variables d'environnement ENV RECIPE_MICROSERVICE_URL=http://172.17.0.1:5002 ENV NUTRITION_MICROSERVICE_URL=http://172.17.0.1:5004 # Définition du répertoire de travail WORKDIR /website_app # Copie des fichiers du repertoire au sein du conteneur COPY . . # Installation des dépendances RUN pip install -r requirements.txt # Commande executée au lancement du conteneur CMD ["python3", "main.py", "5000"] ``` - La variable d'environement `RECIPE_MICROSERVICE_URL` contient l'adresse vers l'API des recettes - La variable d'environement `NUTRITION_MICROSERVICE_URL` contient l'adresse vers l'API des calories ### Lancement du service Déplacement dans le repertoire : ```BASH cd website ``` Construction de l'image Docker depuis le `dockerfile` : ```BASH sudo docker build -t vm_docker_tp2-website . ``` Construction et lancement d'un conteneur Docker basé sur l'image `vm_docker_tp2-website` : ```BASH sudo docker run -p 5003:5000 vm_docker_tp2-website ``` Le service peut ensuite être accedé par navigateur à l'adresse `http://localhost:5003/` : ![image](https://hackmd.io/_uploads/HkjEZ3xTa.png) # Question 4 **cf : [README.md](https://gitlab.isima.fr/fisa-2/vm_docker-tp2/-/blob/master/README.md?ref_type=heads)** # Ressources annexes ## Docker : distinction `ENV` et `ARG` Dans le `dockerfile`, les variables définies via `ENV` et via `ARG` n'ont pas la même portée : ![Portée des variables définies via `ENV` et via `ARG`](https://vsupalov.com/images/docker-env-vars/docker_environment_build_args.png) - Les variables définies par `ENV` sont accessibles du `dockerfile` jusqu'au `container`. Elles permettent de donner des valeurs par défault à des variables d'environnement et sont ainsi utilisées pour stocker des secrets (URL d'API, identifiants de connection à une BDD, ...) - Les variables définies par `ARG` ne sont plus disponibles une fois l'image construite. Un container en execution n'a donc pas accès a ces valeurs. Elles sont uniquement accessible au moment de la construction de l'image Docker et permettent de rendre modulable un `dockerfile` en definisant les valeur des variables `ARG` dynamiquement au moment du lancement de la commande `build` : ``` ARG VAR_NAME 5 --build-arg VAR_NAME=6 # Au moment du lancement de la commande de build ``` ### Sources - [Docker ARG vs ENV](https://vsupalov.com/docker-arg-vs-env/)