Comment utiliser les modules ECMAScript avec Node.js – CloudSavvy IT
Agence web » Actualités du digital » Comment dockeriser une application Web Node.js – CloudSavvy IT

Comment dockeriser une application Web Node.js – CloudSavvy IT

Docker est une plateforme de conteneurisation qui simplifie le packaging et l’exécution des applications. Les conteneurs s’exécutent comme des processus isolés avec leur propre système de fichiers mais partagent le noyau de leur hôte. Docker s’est imposé comme un moyen de mettre en œuvre des environnements de développement reproductibles et des architectures de déploiement distribué.

Node.js est le premier runtime JavaScript pour le développement backend. Pour lancer avec succès un service Web Node.js, vous devez disposer d’un environnement avec le runtime installé, votre code d’application disponible et un mécanisme qui gère les redémarrages automatiques en cas de plantage.

Dans ce guide, nous utiliserons Docker pour conteneuriser une application Node.js simple créée avec le framework Web Express populaire. Docker est un bon moyen de déployer des systèmes basés sur des nœuds car il produit un environnement cohérent qui comprend tout ce dont vous avez besoin pour exécuter votre service. Le démon Docker a intégré la prise en charge du redémarrage des conteneurs défaillants lorsque leur processus de premier plan se bloque, résolvant l’un des défis des déploiements Node.js.

Création de votre projet de nœud

Nous allons ignorer les détails de la mise en œuvre de votre application. Créez un répertoire pour votre projet et ajoutez-y du code serveur. Voici une base app.js qui écoute sur le port 8080 et répond à chaque requête avec une réponse codée en dur :

const express = require("express");
 
const app = express();
app.get("*", (req, res) => res.send("<p>It works!</p>"));
app.listen(8080, () => console.log("Listening on 8080"));

Ajoutez Express à votre projet à l’aide de npm :

npm init
npm install --save express

Démarrez votre application pour tester son fonctionnement :

node app.js

Vous devriez pouvoir visiter localhost:8080 dans votre navigateur pour voir l’exemple de réponse.

Écrire un Dockerfile

Il est maintenant temps de commencer à dockeriser votre projet. Vous avez d’abord besoin d’une image pour votre application. Les images encapsulent votre code et vos dépendances dans un package unique que vous utilisez pour démarrer des instances de conteneur. Les instructions de votre Dockerfile définissent l’état du système de fichiers initial de vos conteneurs.

Voici un Dockerfile qui fonctionne pour l’exemple d’application :

FROM node:16
WORKDIR /app

COPY package.json .
COPY package-lock.json .
RUN npm ci

COPY app.js .
CMD ["app.js"]

Ce Dockerfile sélectionne l’image Docker officielle Node.js comme base via le FROM déclaration. L’image hérite de tout dans la base, puis ajoute du contenu supplémentaire via les instructions suivantes.

Le répertoire de travail est défini sur /app par le WORKDIR ligne. Ce qui suit COPY relevés déposeront des fichiers dans le /app répertoire à l’intérieur de l’image du conteneur.

Installation des dépendances

La prochaine étape consiste à ajouter des npm package.json et courir npm ci. Cela installera les dépendances npm de votre projet – Express dans ce cas – dans le système de fichiers du conteneur.

Ne pas utiliser COPY node_modules/ . copier l’existant node_modules dossier dans votre répertoire de projet – cela vous empêcherait de réutiliser le Dockerfile dans d’autres environnements de construction. Dockerfiles devrait vous permettre de créer des versions cohérentes avec uniquement le contenu de votre référentiel de contrôle de code source. Si un fichier ou un dossier se trouve dans votre .gitignoreil ne doit pas être référencé dans un Dockerfile COPY instruction.

Copie du code d’application

Après npm ci a été exécuté, le code de votre application est copié dans l’image. Le placement de ce COPY instructions après la RUN, le séparant des copies précédentes, est délibéré. Chaque instruction crée un nouveau calque dans votre image ; Le processus de génération de Docker met en cache chaque couche pour accélérer les générations suivantes. Une fois que le contenu d’une couche change, le cache de toutes les couches suivantes sera invalidé.

C’est pourquoi le code d’application doit être copié après npm ci a été exécuté. Le code changera généralement beaucoup plus fréquemment que le contenu de votre fichier de verrouillage npm. Les reconstructions d’image qui n’impliquent que des changements de code ignoreront effectivement le RUN npm ci étape (et toutes les étapes précédentes), accélérant considérablement le processus lorsque vous avez beaucoup de dépendances.

Définition de la commande de l’image

La dernière étape Dockerfile utilise le CMD instruction pour exécuter votre application automatiquement au démarrage du conteneur. Cela fonctionne car l’image de base Node.js est configurée pour utiliser le node processus comme point d’entrée. le CMD est ajouté au point d’entrée hérité, ce qui entraîne node app.js être exécuté comme processus de premier plan pour votre nouvelle image.

Construire votre image

Ensuite, vous devez créer votre image :

docker build -t node-app:latest .

Docker prendra le Dockerfile dans votre répertoire de travail, exécutez les instructions qu’il contient et marquez l’image résultante comme node-app:latest. Le final . (point) spécifie votre répertoire de travail comme contexte de construction d’image. Ceci détermine les chemins qui peuvent être référencés par le COPY instructions dans votre Dockerfile.

Optimisation de la construction

Une façon d’améliorer les performances de construction est d’ajouter un .dockerignore fichier à la racine de votre projet. Donnez au fichier le contenu suivant :

node_modules/

Ce fichier définit les chemins dans votre répertoire de travail qui ne pas être inclus dans le contexte de construction. Vous ne pourrez pas les référencer dans votre Dockerfile. Dans le cas de node_modulesle contenu de ce répertoire n’est pas pertinent pour la construction car nous installons à nouveau les dépendances via le RUN npm ci instruction. En excluant spécifiquement le node_modules déjà présent dans votre répertoire de travail évite d’avoir à copier tous ces fichiers dans l’emplacement de contexte de construction temporaire de Docker. Cela augmente l’efficacité et réduit le temps passé à préparer la construction.

Démarrer un conteneur

À ce stade, vous êtes prêt à exécuter votre application à l’aide de Docker :

docker run -d 
    -p 8080:8080 
    --name my-app 
    --restart on-failure 
    node-app:latest

le docker run La commande est utilisée pour démarrer une nouvelle instance de conteneur à partir d’une image spécifiée. Quelques indicateurs supplémentaires sont ajoutés pour configurer correctement le conteneur pour le cas d’utilisation prévu :

  • -d – Détache votre shell du processus de premier plan du conteneur, l’exécutant efficacement en tant que serveur d’arrière-plan.
  • -p – Lie le port 8080 sur votre hôte au port 8080 à l’intérieur du conteneur (sur lequel notre exemple d’application Express a été configuré pour écouter). Cela signifie du trafic vers localhost:8080 seront acheminés vers le port à conteneurs correspondant. Vous pouvez changer la publication hôte en une valeur différente en modifiant la première partie de la définition de liaison, telle que 8100:8080 pour accéder à votre conteneur sur localhost:8100.
  • --name – Attribue au conteneur un nom convivial que vous pouvez utiliser pour le référencer dans d’autres commandes Docker CLI.
  • --restart – Sélectionne la stratégie de redémarrage à appliquer au conteneur. le on-failure signifie que Docker redémarrera automatiquement le conteneur s’il se termine avec un code d’échec parce que votre application a planté.

L’image construite à l’étape précédente est référencée comme argument final de la docker run commander. L’identifiant du conteneur sera émis dans la fenêtre de votre terminal ; vous devriez pouvoir accéder à votre application Node.js en visitant localhost:8080 de nouveau. Cette fois, le serveur s’exécute dans le conteneur Docker, au lieu d’utiliser le node processus installé sur votre hôte.

Sommaire

Docker vous aide à déployer les services Web Node.js en conteneurisant l’ensemble de l’environnement d’application. Vous pouvez démarrer un conteneur à partir de votre image avec un seul docker run commande sur n’importe quel hôte sur lequel Docker est installé. Cela supprime la complexité de la maintenance des versions de Node.js, de l’installation des modules npm et de la surveillance des situations dans lesquelles votre processus d’application doit être redémarré.

Lorsque vous avez apporté des modifications au code et que vous souhaitez lancer votre mise à jour, reconstruisez votre image Docker et supprimez votre ancien conteneur avec docker rm <container-name>. Vous pouvez ensuite démarrer une instance de remplacement qui utilise l’image révisée.

Vous voudrez peut-être une routine légèrement différente en production. Bien que vous puissiez utiliser une installation Docker standard avec docker run, cela a tendance à être difficile à manier pour toutes les applications, sauf les plus simples. Il est plus courant d’utiliser un outil comme Docker Compose ou Kubernetes pour définir la configuration du conteneur dans un fichier qui peut être versionné dans votre référentiel.

Ces mécanismes vous évitent de répéter votre docker run flags chaque fois que vous démarrez un nouveau conteneur. Ils facilitent également la réplication des conteneurs pour faire évoluer votre service et assurer la redondance. Si vous déployez sur un hôte distant, vous devrez également transférer votre image vers un registre Docker afin qu’elle puisse être « extraite » de votre machine de production.

Une autre considération spécifique à la production est la façon dont vous allez acheminer le trafic vers vos conteneurs. Les liaisons de port peuvent suffire pour commencer, mais vous finirez par atteindre une situation où vous souhaitez plusieurs conteneurs sur un hôte, chacun écoutant sur le même port. Dans ce cas, vous pouvez déployer un proxy inverse pour acheminer le trafic vers des ports de conteneur individuels en fonction des caractéristiques de la demande telles que le nom de domaine et les en-têtes.