LAB : Déploiement application avec docker compose#
Présentation#
Objectifs:#
- Familiarisation avec Docker-compose
- Déploiement de plusieurs services (frontend, backend, proxy, etc.)
- Appropriation de la syntaxe d'un manifeste docker-compose
Architecture#
Dans ce lab, nous allons déployer une application 3-tiers composés des briques suivantes:
- Moodboard-frontend: Conçu en react permet d'exposer l'interface utilisateur
- Moodboard-backend: conçu en springboot, permet d'exposer des API et continet la logique métier
- PostgreSQL: Base de données utilisé pour la persistance des données

Prérequis#
- Connaissance de Docker et de la syntaxe YAML
- Instance docker fonctionnel
- Editeur de code
- Utilitaire installé sur la machine: git
- Avoir un proxy nginx fonctionnel
Déroulement du Lab#
Etape 1 : Récupération du code source#
La commande suivante permet de récupérer le code source des applications backend (Springboot) & frontend (react).
git clone https://github.com/wingufactory/lecloudfacile-devops-labs.git
Bon à savoir:
- Afin d'optimiser la taille des images Docker, nous procéderons à un build multistage.
- Dans la suite, nous appelerons "conteneur temporaire", le conteneur managé entièrement par le moteur de Docker et qui servira pour l'execution des instructions du Dockerfile pour la construction de l'image.
Etape 2 : Examen du dockerfile de l'application backend#
Le dockerfile du backend est déjà dans le répertoire springboot-react-app/moodboard-backend.
Avant de procéder à l'execution des commandes nécessaires, nous allons décrire le contenu afin de savoir ce que chaque instruction permet.
# Stage 1 : Construction de l'artefact (fichier jar) embarquant l'application springboot
# Utilisation de l'image de base maven:3.9.4-eclipse-temurin-17. Le mot clé **AS** permet de nommer le stage, ici "build"
FROM maven:3.9.4-eclipse-temurin-17 AS build
# Définition d'un répertoire de travail à l'intérieur du conteneur temporaire
WORKDIR /app
# Copie du fichier pom.xml contenant les dépendances et
COPY pom.xml .
# Téléchargement des dépendances dans le conteneur temporaire
RUN mvn dependency:go-offline
# Copie des fichiers sources
COPY src ./src
#package de l'application en ignorant les tests.
RUN mvn clean package -DskipTests
# Stage 2 : Création de l'image final qui va démarrer et exposer l'application construite au stage 1
# Utilisation de l'image de base eclipse-temurin:17-jdk-jammy
FROM eclipse-temurin:17-jdk-jammy
# Définition d'unrépertoire de travail à l'intérieur du conteneur temporaire
WORKDIR /app
# Copie de l'artefact créé dans le phase 1 dans le conteneur temporaire
COPY --from=build /app/target/moodboard-backend-0.0.1-SNAPSHOT.jar app.jar
# Exposition du port de l'application
EXPOSE 8080
# Indication de la commande de démarrage de l'application lorsque l'image sera en execution
ENTRYPOINT ["java", "-jar", "app.jar"]
La commande suivante va permettre de créer l'image. Cependant, cette étape peut être facultative si on décide d'inclure le build directement dans le manifeste du docker-compose.
docker build -t moodboard-backend-app:1.0.0 springboot-react-app/moodboard-backend
Etape 3 : Examen du dockerfile de l'application frontend#
Le dockerfile du frontend est déjà dans le répertoire springboot-react-app/moodboard-frontend.
Avant de procéder à l'execution des commandes nécessaires, nous allons décrire le contenu afin de savoir ce que chaque instruction permet.
# Stage 1 : Construction de l'artefact (fichier jar) embarquant l'application springboot
# Utilisation de l'image de base node:18-alpine. Le mot clé **AS** permet de nommer le stage, ici "build"
FROM node:18-alpine AS build
# Définition du répertoire de travail à l'intérieur du conteneur temporaire
WORKDIR /app
# Ajout de la variable d'environnement REACT_APP_API_URL qui contiendra l'url de l'API exposé par le backend
ARG REACT_APP_API_URL
ENV REACT_APP_API_URL $REACT_APP_API_URL
# Copie des fichiers package.json et package-lock.json contenant les dépendances
COPY package*.json ./
# Installation des dépendences
RUN npm install
# Copie du code source de l'application
COPY . .
# Construction de l'application react pour la production
RUN npm run build
# Stage 2 : Création de l'image final qui va démarrer et exposer l'application construite au stage 1
# Utilisation de l'image nginx
FROM nginx:alpine
#Copie des fichiers statiques créé dans la phase 1
COPY --from=build /app/build /usr/share/nginx/html
# Exposition du port su server Web
EXPOSE 80
# Démarrage du serveur web Nginx
CMD ["nginx", "-g", "daemon off;"]
La commande suivante va permettre de créer l'image. Cependant, cette étape peut être facultative si on décide d'inclure le build directement dans le manifeste du docker-compose.
docker build -t moodboard-frontend-app:1.0.0 springboot-react-app/moodboard-frontend
Etape 4 : Creation du manifeste docker compose#
Dans cette étape, nous allons construire ensemble le manifeste docker-compose en commentant l'utilité de chaque instruction.
Tout d'abord, il faut créer un fichier docker-compose.yaml dans le répertoire springboot-react-app/
Le contenu de ce fichier est décrit dans ce qui suit:
# Indication de la version de l'API
version: '3.8'
# Création d'un volume nommé <pgdata> pour la persistance des données. Il sera utilisé par la base de données Postgresql.
volumes:
pgdata:
# Création d'un réseau nommé <app-network> pour l'ensemble des conteneurs qui vont appartenir à la stack et déclaration du réseau <frontend> utilisé par le proxy nginx.
networks:
app-network:
frontend:
name: frontend
external: true
# Déclaration liste des services
services:
# Service database: Base de données Postgresql
database:
# Nom du comteneur
container_name: database
# Choix de l'image
image: postgres:16.2-alpine
# Toujours forcer le rédémarrage du conteneur en cas de problème.
restart: always
# Déclaration des variables d'environnement requises
environment:
POSTGRES_USER: ${DATASOURCE_USERNAME}
POSTGRES_PASSWORD: ${DATASOURCE_PASSWORD}
POSTGRES_DB: lecloudfacile
# Montage du volume pour la persitence des données
volumes:
- pgdata:/var/lib/postgresql/data
# Attachement du service au réseau <app-network>
networks:
- app-network
# Service adminer: Client web pour B-base de données
adminer:
# Nom du comteneur
container_name: adminer
# Choix de l'image
image: adminer
# Toujours forcer le rédémarrage du conteneur en cas de problème.
restart: always
# Indiquer que ce service dépend du service <database>
depends_on:
- database
# Attachement du service aux réseaux <app-network> pour communiquer avce la DB et <frontend> pour communiquer avec le proxy
networks:
- app-network
- frontend
# Service backend: Application springboot contenant le logique métier et exposant des apis pour faciliter la communication.
backend:
# Nom du comteneur
container_name: backend
# Cette phase permet de construire l'image Docker qui sera utilisé en s'appuyant sur le dockerfile. Le parametre <context> permet d'indiquer l'emplacement du répertoire sur lequel le build sera executé.
build:
context: ./moodboard-backend
dockerfile: Dockerfile
# Indiquer que ce service dépend du service <database>
depends_on:
- database
# Déclaration des variables d'environnement requises
environment:
SPRING_DATASOURCE_URL: ${DATASOURCE_URL}
SPRING_DATASOURCE_USERNAME: ${DATASOURCE_USERNAME}
SPRING_DATASOURCE_PASSWORD: ${DATASOURCE_PASSWORD}
FRONTEND_APP_URL: ${APP_URL}
SPRING_JPA_HIBERNATE_DDL_AUTO: update
# Attachement du service aux réseaux <app-network> pour communiquer avce la DB et <frontend> pour communiquer avec le proxy
networks:
- app-network
- frontend
# Service frontend: Application react qui exposent les pages de l'application.
frontend:
# Nom du comteneur
container_name: frontend
# Cette phase permet de construire l'image Docker qui sera utilisé en s'appuyant sur le dockerfile. Le parametre <context> permet d'indiquer l'emplacement du répertoire sur lequel le build sera executé.
build:
context: ./moodboard-frontend
dockerfile: Dockerfile
args:
REACT_APP_API_URL: ${REACT_APP_API_URL}
# Déclaration des variables d'environnement requises
environment:
REACT_APP_API_URL: ${REACT_APP_API_URL}
# Indiquer que ce service dépend du service <backend>
depends_on:
- backend
# Attachement du service aux réseaux <app-network> pour communiquer avce la DB et <frontend> pour communiquer avec le proxy
networks:
- app-network
- frontend
Etape 5 : Création du fichier .env#
Le fichier .env va permettre de stocker les informations confidentielles telle que le mot de passe de la base de données Postgresql. Ce fichier ne sera pas versionné et sera créé localement dans chaque environnement sur lequel derva s'exeuter les servies.
Ci-dessous, le contenu du fichier .env en conformité avec le contenu du fichier docker-compose défini plus haut.
NB: Le fichier doit être dans le même emplcament que le fichier docker-compose.yaml
DATASOURCE_URL="jdbc:postgresql://database:5432/lecloudfacile"
DATASOURCE_USERNAME=lecloudfacile
DATASOURCE_PASSWORD=TwwsVdt9INkUATx
REACT_APP_API_URL=http://api.moodboard.xyz/api/feedback
APP_URL=http://app.moodboard.xyz
Etape 6: Execution des services#
A ce stade, toutes les configurations sont finalisées. Il ne reste plus qu'à démarrer les services
- Démarrage des services
La commande ci-dessous permet de démarrer tous les services en arrière-plan.
docker compose up -d
- Affichage des conteneurs
docker ps
NB: Certaines container en l'occurence le backend et le frontend peuvent échouer au démarrage. C'est normal. Il faudra ajouter la configuration du proxy pour les rétablir.
Etape 7: Mise à jour de la configuration du proxy#
Le répertoire lecloudfacile-devops-labs/nginx-proxy/conf.d/moodboard doit contenir la configuration du proxy nginx pour la gestion des requêtes entrantes en ce concerne l'application moodboard. Elle permettra dans notre cas de rediriger le trafic vers le bon conteneur. Nous aurons un fichier de conf par application que nous voulons exposer.
- Option 1 : Création des fichiers de configurations à partir des templates
devops@lecloudfacile:~$ cd lecloudfacile-devops-labs/nginx-proxy/
devops@lecloudfacile:~$ cp conf.d/moodboard/adminer-moodboard.conf.template conf.d/adminer-moodboard.conf
devops@lecloudfacile:~$ cp conf.d/moodboard/backend-moodboard.conf.template conf.d/backend-moodboard.conf
devops@lecloudfacile:~$ cp conf.d/moodboard/frontend-moodboard.conf.template conf.d/frontend-moodboard.conf
-
Options 2 : Création fichiers de configurations from scratch
-
Créer un fichier conf.d/moodboard/frontend-mooadboard.conf pour l'accès au frontend de l'application
```yaml server { listen 80; server_name app.moodboard.xyz;
location / { proxy_pass http://frontend:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }} ```
-
Créer un fichier conf.d/moodboard/backend-mooadboard.conf pour l'accès au backend de l'application
```yaml server { listen 80; server_name api.moodboard.xyz;
location / { proxy_pass http://backend:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }} ```
-
Créer un fichier conf.d/moodboard/adminer-mooadboard.conf pour l'accès au client de la base de données
```yaml server { listen 80; server_name adminer.moodboard.xyz;
location / { proxy_pass http://adminer:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }} ```
Etape 8: Recharge de la configuration du proxy#
Il faudra recharger la configuration du proxy pour prendre en compte les modifications apportées à l'étape 7.
devops@lecloudfacile:~$ docker exec -ti proxy nginx -s reload
Etape 9: Accès à l'application#
Ouvrez un navigateur et tapez l'adresse suivante : http://app.moodboard.xyz

Etape 10: Arrétez l'application#
- Arrêt de l'applictaion
Il faudra se positionner dans le répertoire lecloudfacile-devops-labs/springboot-react-app/
devops@lecloudfacile:~$ docker compose down
Il faudra se positionner dans le répertoire lecloudfacile-devops-labs/nginx-proxy/
- Suppression de la configuration du proxy
Il faudra nettoyer les fichiers de configurations du proxy au risque de voir le proxy crashé de façon continue.
devops@lecloudfacile:~$ rm -rf conf.d/adminer-moodboard.conf conf.d/backend-moodboard.conf conf.d/frontend-moodboard.conf
- recharge de la configuration du proxy
devops@lecloudfacile:~$ docker exec -ti proxy nginx -s reload