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.
Sommaire
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 .gitignore
il 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_modules
le 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 verslocalhost: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 que8100:8080
pour accéder à votre conteneur surlocalhost: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. leon-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.