En ayant marre d'avoir à gérer x versions de de NodeJS sur ma machine avec pour chacune ses dépendances et incompatibilités, et de devoir se souvenir pour chaque projet quelle version utiliser, j'ai fini par externaliser cette gestion à docker, comme je le fais déjà depuis longtemps pour php, mysql, SolR...
Ainsi, chaque projet a son image docker NodeJS, configurée aux petits oignons, et plus de nodejs installé sur ma machine.
Je n'utilisais cette image qu'en local pour commencer, mais je suis allé un peu plus loin en utilisant cette même image docker dans le cadre de mes processus de déploiements automatisés, afin de lancer les tâches front (compilation des css et JS, aggrégation, minification des fichiers... bref l'ensemble des tâches gulp nécessaires. Mais cela peut marcher avec Yarn avec peu de modifications.
Pour ce faire, j'avais besoin que mon image soit "publique" et disponible sur un dépôt d'image docker (le plus connus étant https://hub.docker.com/)
Pour commencer j'ai créé un dépot github (https://github.com/kgaut/docker-node) visant à contenir mes images, vu que j'avais besoin de plusieurs images (une par version de node) j'ai choisi d'utiliser des sous-dossiers pour chaque version majeure de NodeJS.
Pour chaque version, un DockerFile, uniquement la première ligne diffère d'un dossier à l'autre, voici l'exemple pour la version 13 :
FROM node:13-alpine
RUN apk add --update \
python \
python-dev \
py-pip \
build-base \
git \
openssh-client \
optipng \
autoconf \
jpeg-dev \
zlib-dev \
automake \
libtool \
pkgconfig \
rsync \
&& pip install virtualenv \
&& rm -rf /var/cache/apk/*
RUN npm install -g gulp
WORKDIR /app
RUN npm set progress=false
RUN npm install
L'image se base sur la version linux alpine de Node 13, j'ajoute quelques dépendances utiles (rsync, libtool, jpeg-dev, git...) installation via node de Gulp, définition de /app comme dossier de travail...
J'ai ensuite créé un nouveau dépôt sur hub.docker.com (https://hub.docker.com/repository/docker/kgaut/node) j'ai configuré le « build » d'image pour fonctionner avec mon organisation par dossier :
Ainsi le fichier ./11/Dockerfile gère le tag 11 de mon image docker. Et à chaque fois que je mets le dépôt git à jour, pour ajouter une dépendance par exemple, les images sont reconstruites.
Utilisation de l'image
Via docker-compose
En local, j'utilise docker compose pour administrer tous mes services, j'ajoute donc l'image à mon fichier docker-compose.yml comme n'importe quel autre service :
node:
image: kgaut/node:13
container_name: "monprojet_nodejs"
volumes:
- ./:/app
tty: true
je précise la version de node que je souhaite (13 dans ce cas) et le monte le dossier courant sur /app.
Pour ensuite exécuter des taches je passe par la commande suivante :
docker-compose exec node COMMANDE
# exemples :
docker-compose exec node npm ci
docker-compose exec node gulp build
Via docker
Lancement de l'image (toujours en montant le dossier courant dans /app) :
docker run -t -i -v $(eval pwd):/app kgaut/node:13 bash
Cela ouvre une connexion ssh dans le container et je peux ainsi exécuter les commandes nécessaires :
npm ci
gulp build
Avec Gitlab CI
Dans un job de CI je peux préciser quelle image docker utiliser, mon image étant publique elle est donc utilisable au sein d'un job de CI, voici un exemple :
preprod_assets:
stage: Postdeploy
image: kgaut/node:13
rules:
- if: $CI_COMMIT_BRANCH == "preprod" && $CI_PIPELINE_SOURCE != "schedule"
environment:
name: preprod
script:
- npm ci
- gulp build
- # Ajouter ici les tâches de transfert, vidage de cache...
Plus d'informations ?
N'hésitez-pas à me contacter en commentaire ou via twitter si une partie n'est pas claire. Si vous souhaitez aller plus loin avec docker, docker-compose ou gitlab et la CI je peux aussi vous proposer des formations adaptées à vos besoins.
Commentaires
Sinon il y avait ce bon vieux nvm https://github.com/nvm-sh/nvm
Oui, mais NVM est plus relou à utiliser en CI, et j'en avais marre de basculer d'une version à l'autre dès que je change de projet...
Là plus du tout de nodejs sur ma machine !
A la place d'utiliser une suppression manuel du cache d'APK dans les Dockerfiles, tu peux mettre l'option "--no-cache".
Ajouter un commentaire