[TOC]
# Question 3

## 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`

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>" .
```

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

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
```

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`

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` :

:::
:::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`

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`

:::
### 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`

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`


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/` :

# 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 :

- 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/)