Création dockerfile pour backend Nodejs

Création dockerfile pour backend Nodejs

Publié le


Do not index
Do not index
Primary Keyword
Lié à Analyse sémantique (Articles liés) 1
Lié à Analyse sémantique (Articles liés)
Statut rédaction
A écrire
Lié à Analyse sémantique (Articles liés) 2

Node.js

Node.js est une plateforme logicielle open-source qui permet d'exécuter du code JavaScript côté serveur. Il utilise le moteur JavaScript V8 de Google Chrome pour exécuter le code, ce qui le rend extrêmement performant. Node.js est largement utilisé pour développer des applications web en temps réel, des API REST, des outils de ligne de commande et bien plus encore. Pour illustrer une application Node.js, prenons l'exemple disponible sur ce lien. Cette application est une simple application web qui utilise le framework Express.js pour servir des pages web statiques et gérer les routes.

Dockerfile

Un Dockerfile est un fichier texte sans format qui contient toutes les instructions commandées par l'utilisateur pour créer une image Docker. En d'autres termes, les Dockerfiles sont comme des scripts shell automatisés qui contiennent des commandes pour assembler une image Docker qui peut ensuite être utilisée pour créer des conteneurs Docker.
 
Les Dockerfiles commencent généralement par définir une image de base à partir de laquelle ils construisent. Cela est généralement une image de système d'exploitation qui est ensuite modifiée pour inclure des dépendances supplémentaires et des configurations nécessaires pour l'application que vous essayez de contenir.
Par exemple, si vous avez une application Node.js, votre Dockerfile commencera probablement par une image de base qui a Node.js installé.
 
Les Dockerfiles utilisent une série de commandes pour définir et créer l'image Docker. Certaines des commandes les plus courantes incluent :
  • FROM : Définit l'image de base à partir de laquelle vous construisez
  • RUN : Exécute une commande, utile pour installer des packages sur l'image
  • COPY et ADD : Copie des fichiers de votre système de fichiers local dans l'image Docker
  • WORKDIR : Définit le répertoire de travail pour les instructions suivantes
  • CMD : Fournit des valeurs par défaut qui peuvent être exécutées lors de l'exécution de l'image Docker
 
Voici un exemple de Dockerfile optimisé pour une application Node.js :
# Définir une variable d'argument pour spécifier la version de Node.js à utiliser
ARG NODE_VERSION=12.2.0-slim

# Utiliser l'image Node.js spécifiée par la variable d'argument
FROM node:$NODE_VERSION AS builder
ARG NPM_ARGS
ENV NPM_ARGS=${NPM_ARGS}

# Create user, http://redhatgov.io/workshops/security_containers/exercise1.2/
# Créer un nouvel utilisateur et un nouveau groupe pour exécuter notre application
# C'est une bonne pratique pour la sécurité, car cela évite d'exécuter l'application en tant que root
RUN groupadd -r nodejs -g 433 && \
    useradd -u 431 -r -g nodejs -s /sbin/nologin -c "Docker image user" nodejs

# Créer un répertoire pour l'application et on change la propriété de ce répertoire à notre nouvel utilisateur
RUN mkdir /home/nodejs && \
    chown -R nodejs:nodejs /home/nodejs

# Changer l'utilisateur courant à notre nouvel utilisateur
USER nodejs

# Créer et définir un répertoire pour l'application
WORKDIR /home/nodejs

# Copier le package.json et le package-lock-json
COPY --chown=nodejs:nodejs package*.json ./

# Installer les dépendances
RUN npm install --only=production

# Copier le reste du code de l'application
COPY --chown=nodejs:nodejs . .

# Construire l'application
RUN npm run build

# Créer une nouvelle image à partir de l'image de base Node.js
FROM node:$NODE_VERSION

WORKDIR /home/nodejs

# Copier les dépendances et le code construit depuis l'image builder
COPY --from=builder --chown=nodejs:nodejs /home/nodejs .

# Exposer le port sur lequel l'application va s'exécuter
EXPOSE 8080

# Définir la commande pour démarrer l'application
CMD ["npm", "start"]
 
  • L’instruction ARG NODE_VERSION définit une variable NODE_VERSION qui est utilisée pour spécifier la version de l'image Node.js à utiliser. Dans cet exemple, nous utilisons la version 12.2.0-slim.
  • FROM définit l'image de base à utiliser pour les étapes suivantes. Dans cet exemple, nous utilisons l'image Node.js spécifiée par la variable NODE_VERSION.
  • L'instruction AS dans FROM node:$NODE_VERSION AS builder est utilisée pour nommer une étape de construction. Dans ce cas, l'étape de construction est nommée builder. Cette étape est utilisée pour construire l'application et ses dépendances. En nommant cette étape, vous pouvez réutiliser les résultats de cette étape dans des étapes ultérieures. Par exemple, vous pouvez copier les fichiers de cette étape dans une autre étape avec l'instruction COPY --from=builder.
  • Les instructions ARG et ENV sont utilisées pour définir des variables d'environnement qui peuvent être utilisées dans les instructions suivantes.
  • COPY copie les fichiers package.json et package-lock.json dans notre image. Ces fichiers sont nécessaires pour installer les dépendances de notre application.
  • L'option --chown=nodejs:nodejs dans l'instruction COPY est utilisée pour changer la propriété des fichiers copiés. Dans ce cas, les fichiers sont copiés avec l'utilisateur nodejs et le groupe nodejs comme propriétaires. C'est une bonne pratique pour la sécurité, car cela évite que les fichiers soient copiés avec l'utilisateur root comme propriétaire, ce qui pourrait présenter des risques de sécurité.
  • RUN npm install installe les dépendances de notre application. L'option --only=production garantit que seules les dépendances nécessaires pour exécuter l'application en production sont installées.
 
Pour construire une image à partir de ce Dockerfile, vous pouvez utiliser la commande docker build depuis le dossier contenant le Dockerfile :
docker build -t my-nodejs-app .
 
Et pour lancer un conteneur à partir de cette image, vous pouvez utiliser la commande docker run :
docker run -p 8000:8080 -d my-nodejs-app
 
  • Veillez à modifier my-nodejs-app par le nom de votre image
  • -p 8000:8080 : Cette option est utilisée pour mapper le port de l'hôte (votre machine) au port du conteneur. Cela signifie que si votre application à l'intérieur du conteneur écoute sur le port 8080, vous pouvez y accéder en utilisant le port 8000 de votre machine
  • -d : Cette option est utilisée pour démarrer le conteneur en mode détaché. Cela signifie que le conteneur s'exécute en arrière-plan et ne bloque pas votre terminal

.dockerignore

Le fichier .dockerignore est un fichier texte qui indique à Docker d'ignorer certains fichiers et dossiers lors de la construction d'une image Docker à partir d'un Dockerfile. Il fonctionne de manière similaire à un fichier .gitignore, qui est utilisé pour ignorer certains fichiers et dossiers lors de l'utilisation de Git.
 
Lorsque vous construisez une image Docker, Docker copie le contexte de construction (c'est-à-dire le répertoire dans lequel vous exécutez la commande de construction Docker) dans l'image Docker. Cela inclut tous les fichiers et dossiers dans ce répertoire. Cependant, il y a souvent des fichiers et des dossiers que vous ne voulez pas inclure dans votre image Docker, comme les dépendances de développement, les fichiers de configuration spécifiques à l'environnement, les dossiers de cache, etc. En les incluant dans un fichier .dockerignore, vous pouvez dire à Docker de ne pas les copier dans l'image Docker.
 
L'utilisation d'un fichier .dockerignore est une bonne pratique pour plusieurs raisons :
  • Réduire la taille de l'image : En excluant les fichiers inutiles, vous pouvez réduire la taille de votre image Docker, ce qui peut accélérer le temps de déploiement et réduire l'espace disque nécessaire pour stocker l'image.
  • Sécurité : En excluant les fichiers sensibles (comme les fichiers de configuration contenant des mots de passe), vous pouvez éviter qu'ils ne soient inclus dans l'image Docker, où ils pourraient être exposés à des utilisateurs non autorisés.
  • Performance : En excluant les fichiers inutiles, vous pouvez accélérer le temps de construction de l'image Docker, car Docker n'a pas besoin de copier ces fichiers dans l'image.
 
Voici un exemple de fichier .dockerignore optimisé pour une application Node.js :
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules

# Logs
logs
*.log
npm-debug.log

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Ignore test files
**/*.spec.js

# Ignore production files
dist

# Ignore Docker files
.dockerignore
Dockerfile
docker-compose.yml

# Ignore Git files
.git
.gitignore

# Ignore Kubernetes files
kubernetes
 
  • node_modules : Ce dossier contient les dépendances du projet Node.js. Il est généralement volumineux et n'est pas nécessaire pour la construction de l'image Docker car les dépendances seront installées lors de la construction de l'image.
  • .grunt : Ce dossier est utilisé par Grunt, un outil de construction JavaScript, pour stocker des données temporaires.
  • **/*.spec.js : Cette ligne exclut tous les fichiers de test, qui ne sont pas nécessaires pour l'exécution de l'application.
  • dist : Ce dossier contient généralement les fichiers de production, qui seront construits lors de la construction de l'image Docker.
  • .dockerignore, Dockerfile, docker-compose.yml : Ces fichiers sont spécifiques à Docker et ne sont pas nécessaires pour l'exécution de l'application à l'intérieur du conteneur Docker. En les ajoutant au .dockerignore, on s'assure qu'ils ne sont pas copiés inutilement dans l'image Docker, ce qui réduit la taille de l'image et améliore les performances de construction. De plus, cela peut également aider à prévenir l'inclusion accidentelle de données sensibles qui pourraient être présentes dans ces fichiers.
  • logs, *.log, npm-debug.log : Ces lignes excluent les fichiers de journalisation qui ne sont pas nécessaires pour l'exécution de l'application.
  • pids, *.pid, *.seed : Ces fichiers sont généralement utilisés pour stocker les ID de processus et les données initiales chargées dans la base de données lors de la création de l'application, qui ne sont pas nécessaires dans une image Docker.
  • lib-cov, coverage : Ces dossiers sont utilisés pour stocker les informations de couverture de code (mesure de la qualité des tests et s'assure que toutes les parties du code sont testées) qui ne sont pas nécessaires pour l'exécution de l'application.
  • .lock-wscript, build/Release : Ces fichiers sont utilisés pour la configuration de la construction et les addons binaires compilés, qui ne sont pas nécessaires dans une image Docker
 

Conclusion

En résumé, Docker offre une manière flexible et efficace de déployer des applications Node.js. En utilisant les Dockerfile et les fichiers .dockerignore, nous pouvons créer des environnements reproductibles, isoler nos applications et optimiser la taille de nos images Docker. Cela rend le processus de déploiement plus fluide et plus fiable, nous permettant de nous concentrer sur le développement de fonctionnalités incroyables pour nos utilisateurs.

S'inscrire à la newsletter DevSecOps Keltio

Pour recevoir tous les mois des articles d'expertise du domaine

S'inscrire

Écrit par

Kévin Didelot
Kévin Didelot

Kévin est notre super expert DevSecOps et le fondateur de Keltio 👨🏻‍💻 

Écrit par

Sujets