L'auteur du matériel, dont nous publions la traduction aujourd'hui, est un ingénieur DevOps. Il dit qu'il doit utiliser
Docker . En particulier, cette plate-forme de gestion de conteneurs est utilisĂ©e Ă diffĂ©rentes Ă©tapes du cycle de vie des applications Node.js. L'utilisation de Docker, une technologie qui a rĂ©cemment Ă©tĂ© extrĂȘmement populaire, vous permet d'optimiser le processus de dĂ©veloppement et de sortie des projets Node.js en production.

Nous publions maintenant une
sĂ©rie d'articles sur Docker, conçus pour ceux qui veulent apprendre cette plate-forme pour son utilisation dans diverses situations. Le mĂȘme matĂ©riel se concentre principalement sur l'utilisation professionnelle de Docker dans le dĂ©veloppement de Node.js.
Qu'est-ce qu'un docker?
Docker est un programme conçu pour organiser la virtualisation au niveau du systĂšme d'exploitation (conteneurisation). Au cĆur des conteneurs se trouvent des images en couches. En termes simples, Docker est un outil qui vous permet de crĂ©er, dĂ©ployer et exĂ©cuter des applications Ă l'aide de conteneurs indĂ©pendants du systĂšme d'exploitation sur lequel ils s'exĂ©cutent. Le conteneur comprend une image du systĂšme d'exploitation de base nĂ©cessaire au fonctionnement de l'application, la bibliothĂšque dont dĂ©pend cette application et cette application elle-mĂȘme. Si plusieurs conteneurs s'exĂ©cutent sur le mĂȘme ordinateur, ils utilisent ensemble les ressources de cet ordinateur. Les conteneurs Docker peuvent emballer des projets créés Ă l'aide de diverses technologies. Nous sommes intĂ©ressĂ©s par des projets basĂ©s sur Node.js.
Création d'un projet Node.js
Avant de compresser un projet Node.js dans un conteneur Docker, nous devons créer ce projet. Faisons-le. Voici le fichier
package.json
de ce projet:
{ "name": "node-app", "version": "1.0.0", "description": "The best way to manage your Node app using Docker", "main": "index.js", "scripts": { "start": "node index.js" }, "author": "Ankit Jain <ankitjain28may77@gmail.com>", "license": "ISC", "dependencies": { "express": "^4.16.4" } }
Pour installer les dépendances du projet, exécutez la commande
npm install
. Au cours de cette commande, entre autres, le fichier
package-lock.json
sera créé. Créez maintenant le fichier
index.js
, qui contiendra le code du projet:
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('The best way to manage your Node app using Docker\n'); }); app.listen(3000); console.log('Running on http://localhost:3000');
Comme vous pouvez le voir, nous avons dĂ©crit ici un serveur simple qui renvoie du texte en rĂ©ponse Ă des requĂȘtes.
Créer un Dockerfile
Maintenant que l'application est prĂȘte, parlons de la façon de l'intĂ©grer dans un conteneur Docker. Ă savoir, il s'agira de la partie la plus importante de tout projet basĂ© sur Docker, Ă propos du Dockerfile.
Un Dockerfile est un fichier texte qui contient des instructions pour créer une image Docker pour une application. Les instructions de ce fichier, si elles n'entrent pas dans les détails, décrivent la création de couches d'un systÚme de fichiers à plusieurs niveaux, qui a tout ce dont une application a besoin pour fonctionner. La plate-forme Docker peut mettre en cache des couches d'images, ce qui, lors de la réutilisation de couches qui sont déjà dans le cache, accélÚre le processus de création d'images.
En programmation orientĂ©e objet, il existe une chose telle qu'une classe. Les classes sont utilisĂ©es pour crĂ©er des objets. Dans Docker, les images peuvent ĂȘtre comparĂ©es Ă des classes et les conteneurs peuvent ĂȘtre comparĂ©s Ă des instances d'images, c'est-Ă -dire Ă des objets. ConsidĂ©rez le processus de gĂ©nĂ©ration d'un Dockerfile, qui nous aidera Ă comprendre cela.
Créez un Dockerfile vide:
touch Dockerfile
Puisque nous allons crĂ©er un conteneur pour l'application Node.js, la premiĂšre chose que nous devons mettre dans le conteneur sera l'image de base du nĆud, qui peut ĂȘtre trouvĂ©e sur le
Docker Hub . Nous utiliserons la version LTS de Node.js. Par conséquent, la premiÚre déclaration de notre Dockerfile sera la déclaration suivante:
FROM node:8
AprĂšs cela, crĂ©ez un rĂ©pertoire pour notre code. En mĂȘme temps, grĂące Ă l'instruction
ARG
utilisée ici, nous pouvons, si nécessaire, spécifier le nom du répertoire d'application autre que
/app
lors de l'assemblage du conteneur. Vous trouverez des détails sur ce manuel
ici .
Puisque nous utilisons l'image Node, les plates-formes Node.js et npm y seront déjà installées. En utilisant ce qui est déjà dans l'image, vous pouvez organiser l'installation des dépendances du projet. En utilisant l'indicateur
--production
(ou si la
NODE_ENV
environnement
NODE_ENV
définie sur
production
), npm n'installera pas les modules répertoriés dans la section
devDependencies
du fichier
devDependencies
.
Ici, nous
package*.json
fichier
package*.json
dans l'image, au lieu, par exemple, de copier tous les fichiers du projet. Nous le faisons précisément parce que les instructions Dockerfile
RUN
,
COPY
et
ADD
créent des couches d'image supplémentaires, vous pouvez donc utiliser les fonctionnalités de mise en cache des couches de la plateforme Docker. Avec cette approche, la prochaine fois que nous collecterons une image similaire, Docker cherchera s'il est possible de réutiliser des couches d'images qui sont déjà dans le cache, et si c'est le cas, il tirera parti de ce qui est déjà là , au lieu d'en créer de nouvelles couches. Cela vous permet de gagner sérieusement du temps lors de l'assemblage de couches au cours de travaux sur de grands projets, qui incluent de nombreux modules npm.
Copiez maintenant les fichiers du projet dans le répertoire de travail actuel. Ici, nous n'utiliserons pas l'instruction
ADD , mais l'instruction
COPY . En fait, dans la plupart des cas, il est recommandé de privilégier l'instruction
COPY
.
L'instruction
ADD
, par rapport Ă
COPY
, a certaines fonctionnalités qui, cependant, ne sont pas toujours nécessaires. Par exemple, nous parlons d'options pour décompresser les archives .tar et télécharger des fichiers par URL.
Les conteneurs Docker sont des environnements isolés. Cela signifie que lorsque nous lancerons l'application dans le conteneur, nous ne pourrons pas interagir directement avec elle sans ouvrir le port sur lequel cette application écoute. Afin d'informer Docker qu'il existe une application dans un certain conteneur écoutant sur un certain port, vous pouvez utiliser l'instruction
EXPOSE .
à ce jour, nous, en utilisant le Dockerfile, avons décrit l'image que l'application contiendra et tout ce dont elle a besoin pour réussir le lancement. Ajoutez maintenant l'instruction au fichier qui vous permet de démarrer l'application. Il s'agit d'une instruction
CMD . Il vous permet de spĂ©cifier une certaine commande avec des paramĂštres qui seront exĂ©cutĂ©s au dĂ©marrage du conteneur et, si nĂ©cessaire, peuvent ĂȘtre remplacĂ©s par des outils de ligne de commande.
Voici Ă quoi ressemblera le Dockerfile fini:
FROM node:8
Assemblage d'images
Nous avons préparé un fichier Dockerfile contenant des instructions pour la construction de l'image, sur la base duquel un conteneur avec une application en cours d'exécution sera créé. Assemblez l'image en exécutant une commande de la forme suivante:
docker build --build-arg <build arguments> -t <user-name>/<image-name>:<tag-name> /path/to/Dockerfile
Dans notre cas, cela ressemblera Ă ceci:
docker build --build-arg APP_DIR=var/app -t ankitjain28may/node-app:V1 .
Dockerfile a une instruction
ARG
qui décrit l'argument
APP_DIR
. Ici, nous définissons sa signification. Si cela n'est pas fait, il prendra alors la valeur qui lui est affectée dans le fichier, c'est-à -dire
app
.
AprÚs avoir assemblé l'image, vérifiez si Docker la voit. Pour ce faire, exécutez la commande suivante:
docker images
En rĂ©ponse Ă cette commande, approximativement les Ă©lĂ©ments suivants devraient ĂȘtre sortis.
Images DockerLancement d'image
AprÚs avoir assemblé l'image Docker, nous pouvons l'exécuter, c'est-à -dire en créer une instance, représentée par un conteneur de travail. Pour ce faire, utilisez une commande de ce type:
docker run -p <External-port:exposed-port> -d --name <name of the container> <user-name>/<image-name>:<tag-name>
Dans notre cas, cela ressemblera Ă ceci:
docker run -p 8000:3000 -d --name node-app ankitjain28may/node-app:V1
Nous demanderons au systĂšme des informations sur le fonctionnement des conteneurs Ă l'aide de cette commande:
docker ps
En réponse à cela, le systÚme doit produire quelque chose comme ceci:
Conteneurs DockerJusqu'à présent, tout se passe comme prévu, bien que nous n'ayons pas encore essayé d'accéder à l'application en cours d'exécution dans le conteneur. à savoir, notre conteneur, nommé
node-app
, écoute sur le port
8000
. Afin d'essayer d'y accĂ©der, vous pouvez ouvrir un navigateur et y accĂ©der Ă
localhost:8000
. De plus, afin de vérifier l'intégrité du conteneur, vous pouvez utiliser la commande suivante:
curl -i localhost:8000
Si le conteneur fonctionne vraiment, quelque chose comme celui illustré dans la figure suivante sera retourné en réponse à cette commande.
RĂ©sultat de la vĂ©rification de l'Ă©tat du conteneurSur la base de la mĂȘme image, par exemple, sur la base de tout juste créé, il est possible de crĂ©er de nombreux conteneurs. De plus, vous pouvez envoyer notre image au registre Docker Hub, ce qui permettra Ă d'autres dĂ©veloppeurs de tĂ©lĂ©charger notre image et de lancer les conteneurs appropriĂ©s Ă la maison. Cette approche simplifie le travail avec les projets.
Recommandations
Voici quelques suggestions qui mĂ©ritent d'ĂȘtre examinĂ©es afin de tirer parti de la puissance de Docker et de crĂ©er des images aussi compactes que possible.
â1. CrĂ©ez toujours un fichier .dockerignore
Dans le dossier de projet que vous prévoyez de placer dans le conteneur, vous devez toujours créer un fichier
.dockerignore
. Il vous permet d'ignorer les fichiers et dossiers qui ne sont pas nécessaires lors de la création de l'image. Avec cette approche, nous pouvons réduire le soi-disant contexte de construction, ce qui nous permettra d'assembler rapidement l'image et de réduire sa taille. Ce fichier prend en charge les modÚles de nom de fichier, en cela il est similaire à un fichier
.gitignore
. Il est recommandĂ© d'ajouter une commande Ă
.dockerignore
raison de laquelle Docker ignorera le dossier
/.git
, car ce dossier contient généralement de gros matériaux (en particulier pendant le développement d'un projet) et l'ajouter à l'image entraßne une augmentation de sa taille. De plus, copier ce dossier dans une image n'a pas beaucoup de sens.
â2. Utilisez le processus d'assemblage d'images en plusieurs Ă©tapes
Prenons l'exemple lorsque nous collectons un projet pour une certaine organisation. Ce projet utilise de nombreux packages npm, et chacun de ces packages peut installer des packages supplĂ©mentaires dont il dĂ©pend. L'exĂ©cution de toutes ces opĂ©rations entraĂźne une augmentation du temps passĂ© dans le processus d'assemblage de l'image (bien que cela, grĂące aux capacitĂ©s de mise en cache de Docker, ne soit pas si grave). Pire, l'image rĂ©sultante contenant les dĂ©pendances d'un certain projet est assez grande. Ici, si nous parlons de projets frontaux, nous pouvons rappeler que ces projets sont gĂ©nĂ©ralement traitĂ©s Ă l'aide de bundlers comme webpack, qui permettent de regrouper facilement tout ce dont une application a besoin dans un package de vente. Par consĂ©quent, les fichiers de package npm pour un tel projet ne sont pas nĂ©cessaires. Et cela signifie que nous pouvons nous dĂ©barrasser de ces fichiers aprĂšs avoir construit le projet en utilisant le mĂȘme webpack.
Armé de cette idée, essayez de faire ceci:
Une telle approche, cependant, ne nous conviendra pas. Comme nous l'avons déjà dit, les instructions
RUN
,
ADD
et
COPY
créent des couches mises en cache par Docker, nous devons donc trouver un moyen de gérer l'installation des dépendances, de construire le projet, puis de supprimer les fichiers inutiles avec une seule commande. Par exemple, cela pourrait ressembler à ceci:
Dans cet exemple, il n'y a qu'une seule instruction
RUN
qui installe les dépendances,
node_modules
projet et supprime le dossier
node_modules
. Cela conduit au fait que la taille de l'image ne sera pas aussi grande que la taille de l'image qui inclut le dossier
node_modules
. Nous utilisons les fichiers de ce dossier uniquement pendant le processus de génération du projet, puis nous le supprimons. Certes, cette approche est mauvaise en ce sens que l'installation des dépendances npm prend beaucoup de temps. Vous pouvez éliminer cet inconvénient en utilisant la technologie d'assemblage d'images en plusieurs étapes.
Imaginez que nous travaillons sur un projet frontal qui a de nombreuses dépendances, et que nous utilisons webpack pour construire ce projet. Avec cette approche, nous pouvons, dans le but de réduire la taille de l'image, profiter des capacités de Docker pour l'
assemblage d'images en plusieurs étapes .
FROM node:8 As build
Avec cette approche, l'image résultante est beaucoup plus petite que l'image précédente, et nous utilisons également le
node:alpine
image
node:alpine
, qui est elle-mĂȘme trĂšs petite. Et voici une comparaison d'une paire d'images, au cours de laquelle on peut voir que l'image de
node:alpine
beaucoup plus petite que l'image de
node:8
.
Comparaison des images du rĂ©fĂ©rentiel Nodeâ3. Utiliser Docker Cache
Efforcez-vous d'utiliser les capacitĂ©s de mise en cache de Docker pour crĂ©er vos images. Nous avons dĂ©jĂ prĂȘtĂ© attention Ă cette fonctionnalitĂ© lorsque nous travaillions avec un fichier auquel on accĂ©dait par le
package*.json
noms
package*.json
. Cela rĂ©duit le temps de construction de l'image. Mais cette opportunitĂ© ne doit pas ĂȘtre utilisĂ©e Ă la lĂ©gĂšre.
Supposons que nous décrivions dans Dockerfile l'installation de packages dans une image créée à partir de l'image
Ubuntu:16.04
base
Ubuntu:16.04
:
FROM ubuntu:16.04 RUN apt-get update && apt-get install -y \ curl \ package-1 \ . .
Lorsque le systÚme traitera ce fichier, s'il y a beaucoup de packages installés, les opérations de mise à jour et d'installation prendront beaucoup de temps. Afin d'améliorer la situation, nous avons décidé de tirer parti des capacités de mise en cache des couches de Docker et de réécrire le Dockerfile comme suit:
FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y \ curl \ package-1 \ . .
Maintenant, lors de l'assemblage de l'image pour la premiÚre fois, tout se passe comme prévu, car le cache n'a pas encore été formé. Imaginez maintenant que nous devons installer un autre package,
package-2
. Pour ce faire, nous réécrivons le fichier:
FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y \ curl \ package-1 \ package-2 \ . .
Ă la suite d'une telle commande, le
package-2
ne sera ni installé ni mis à jour. Pourquoi? Le fait est que lors de l'exécution de l'instruction de
RUN apt-get update
, Docker ne voit aucune différence entre cette instruction et l'instruction exécutée précédemment, par conséquent, il prend les données du cache. Et ces données sont déjà dépassées. Lors du traitement de l'instruction
RUN apt-get install
systÚme l'exécute, car elle ne ressemble pas à une instruction similaire dans le Dockerfile précédent, mais pendant l'installation, des erreurs peuvent se produire ou l'ancienne version des packages sera installée. En conséquence, il s'avÚre que les commandes de
update
et d'
install
doivent ĂȘtre exĂ©cutĂ©es dans la mĂȘme instruction
RUN
, comme cela est fait dans le premier exemple. La mise en cache est une fonctionnalité intéressante, mais une utilisation imprudente de cette fonctionnalité peut entraßner des problÚmes.
â4. Minimisez le nombre de couches d'image
Il est recommandé, dans la mesure du possible, de s'efforcer de minimiser le nombre de couches d'image, car chaque couche est le systÚme de fichiers de l'image Docker, ce qui signifie que plus les couches de l'image sont petites, plus elles seront compactes. Lors de l'utilisation du processus à plusieurs étapes d'assemblage d'image, une réduction du nombre de couches dans l'image et une réduction de la taille de l'image sont obtenues.
Résumé
Dans cet article, nous avons examinĂ© le processus de conditionnement des applications Node.js dans des conteneurs Docker et l'utilisation de ces conteneurs. De plus, nous avons fait quelques recommandations qui, soit dit en passant, peuvent ĂȘtre utilisĂ©es non seulement lors de la crĂ©ation de conteneurs pour les projets Node.js.
Chers lecteurs! Si vous utilisez professionnellement Docker lorsque vous travaillez avec des projets Node.js, veuillez partager des recommandations sur l'utilisation efficace de ce systÚme avec les débutants.
