Projet de Fin d'Études : Partie 1 - Dockerizer une API Node.JS pour le développment et la production
Voici le premier article sur mon travail dans le cadre de mon projet de fin d’études d’ingénieur.
Nous sommes une équipe de 7 étudiants, travaillant sur le projet Ecobol. Comme le projet n’est pas encore public, je m’en tiendrai à mon travail sur la mise en œuvre des technologies et des infrastructures.
Aperçu de l’infrastructure
Dockerizer une API REST Node.js
Objectifs : Vitesse et harmonisation des environnements
Le projet ne dure que 2 mois, nous ne voulons pas perdre de temps à installer l’environnement de développement sur les machines de chaque développeur. Le développement dans des conteneurs docker permet également d’éviter les problèmes liés aux systèmes d’exploitation, tous les développeurs travaillant sur le même environnement que le serveur de production.
Gérer les différents environnements
Nous avons deux environnements : development
et production
, qui sont stockés dans la variable d’environnement NODE_ENV
. Le choix de l’environnement a un impact sur les dépendances chargées, et sur le comportement de l’API (par exemple le niveau de logs, l’utilisation de pm2).
Le conteneur doit être capable de fonctionner correctement avec chaque environnement. Il y a 3 éléments majeurs à prendre en compte lors du démarrage de l’API :
- Ne charger que les dépendances nécessaires
- Passer la bonne variable d’environnement
NODE_ENV
- Utiliser la bonne commande pour démarrer l’API (
nodemon
en développement,pm2
en production)
La solution implique un Dockerfile
conditionnel, et plusieurs docker-compose.yml
capables d’utiliser ce Dockerfile.
Dockerfile conditionnel
Voici le Dockerfile
conditionnel :
FROM node:10.16.3
# Création d'un répertoire pour l'application
WORKDIR /usr/src/api-ecobol
# Installation des dépendances de l'application
# Un astérisque est utilisé pour s'assurer que package.json ET package-lock.json sont tous deux copiés
COPY package*.json ./
# Construction du code pour la production uniquement si NODE_ENV est défini à "production".
RUN if [ "$NODE_ENV" = "development" ]; \
then npm install; \
else npm ci --only=production; \
fi
# Intégration du code source
COPY . .
EXPOSE 3000
Le point essentiel ici est la ligne RUN
: si le NODE_ENV
n’est pas développement
, il n’installera que des dépendances de production npm ci --only=production
.
Notez également que ce conteneur ne démarre aucun processus à la fin, ce sera le travail du docker-compose.
Docker-Compose
Une fois que le Dockerfile est prêt, Docker-Compose est utilisé pour le builder et fournir une instance de MongoDB.
docker-compose.yml
version: '3'
services:
api-ecobol:
env_file:
- .env
restart: on-failure
build: .
ports:
- '127.0.0.1:3002:3000'
links:
- mongo
mongo:
image: 'mongo:4'
volumes:
- './data:/data/db'
ports:
- '127.0.0.1:27017:27017'
restart: on-failure
Cela transmet le fichier .env
à notre application correctement, mais ne démarre pas encore l’application.
Pour démarrer l’application pour l’environnement de development
, un autre fichier docker-compose est créé pour gérer certains paramètres spécifiques au développement :
docker-compose.dev.yml
version: '3'
services:
api-ecobol:
environment:
- NODE_ENV=development
volumes:
- .:/usr/src/api-ecobol/
command: ./node_modules/.bin/nodemon server.js
Cela :
- Force
NODE_ENV=development
- Monte le code source sous forme de volume pour que nodemon puisse le surveiller
- Démarre le processus nodemon
De la même manière, l’environnement de production
dispose de son propre fichier docker-compose :
docker-compose.prod.yml
version: '3'
services:
api-ecobol:
command: ./node_modules/.bin/pm2-runtime server.js
environment:
- NODE_ENV=production
Cela :
- Force
NODE_ENV=production
- Démarre le processus pm2
Utiliser ces fichiers docker-compose
Pour lancer l’API de development
, il suffit simplement d’exécuter :
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
Et pour lancer l’API de production
:
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
That’s it ! 🚀