Comment activer le cache npm dans un esclave de génération Jenkins qui s'exécute dans Docker?

13

J'ai une image Docker, appelons-la frontend.image, que j'utilise pour un esclave de génération Jenkins. Le plugin Jenkins Docker fera tourner un conteneur à partir de cette image et construira des artefacts à l'intérieur du conteneur. Tout cela fonctionne très bien. Dans ce cas, le frontend.imageest utilisé pour créer une application AngularJs. Une partie de la construction de cette application angulaire consiste à installer les packages npm requis par l'application.

Ce processus, l'installation de npm, semble prendre beaucoup de temps, il semble que 3 minutes, npm installe toujours chaque paquet à chaque fois.

J'ai donc ajouté un volume pour mon esclave, c'est un volume monté sur l'hôte, le plugin Docker utilisera ce volume à chaque fois qu'il exécutera le conteneur frontal:

entrez la description de l'image ici

L'utilisateur qui exécute la commande npm installest jenkins. npm conserve un cache que vous pouvez trouver avec une commande npm config get cachequi génère/home/jenkins/.npm

C'est pourquoi j'ai le volume hôte /slaves/volumes/tsl.frontend:/home/jenkinsmonté sur mon esclave de conteneur Web.

Je crée mon application Angular à l'aide d'un projet Jenkins, ne génère aucun problème, de nombreux packages npm sont installés. Si ssh dans mon hôte Docker et exécute cmd, ls /slaves/volumes/tsl.frontendje vois beaucoup de packages npm. Cela signifie que le volume de mon hôte pour l'esclave a fonctionné. entrez la description de l'image ici

Maintenant, je reconstruis le projet Jenkins, npm installe à nouveau chaque package, même si le conteneur de construction esclave Docker utilise le montage hôte de volume. Je peux même confirmer en bashing dans le conteneur esclave avec cmd docker exec -it <some_clever_random_container_id> bashpuis cmd su jenkinspuis cmd npm cache lsqui répertorie de nombreux packages npm qui sont mis en cache. entrez la description de l'image ici

Donc, même avec mon volume de montage hôte, qui a d'ailleurs des autorisations chmod 777donc il n'y a pas de problèmes d'autorisations, je ne peux pas npm installutiliser le cache.

Dans ma build Jenkins, qui fait tourner le conteneur esclave Docker, le premier cmd que j'exécute est npm cache lset de nombreux packages sont répertoriés, cela ne signifie-t-il pas que mon volume hôte fonctionne comme prévu et que l'index de cache npm a l'intégrité aka non corrompu?

entrez la description de l'image ici

J'ai essayé la npm installcmd régulière , qui, lorsque j'exécute sur ma machine localhost, installe tous les packages la première fois et presque aucun package la prochaine fois. Et aussi le cache npm "hack" npm --cache-min 9999999 install, tiré de cette réponse SO ainsi que cmdnpm --skip-installed --cache-min 9999999 install

Une question connexe a été publiée sur StackOverflow.

Brian Ogden
la source
Je parierais que l'index du cache n'est pas stocké dans ~ / .npm selon votre description
Tensibai
@Tensibai vous vous trompez et j'en suis très sûr, l'utilisateur est jenkins, parce que c'est ce que vous dites d'une autre manière, parce que j'exécute npm cache ls en tant qu'utilisateur jenkins et qui répertorie les packages, vous dites que l'installation de npm est en cours d'exécution par un autre utilisateur
Brian Ogden
non, je dis que l'index lui-même est probablement stocké ailleurs, dans / usr / local ou quel que soit le chemin dans lequel npm est installé ou autre, je n'en ai aucune idée. Cela sonne juste comme si npm agit comme s'il n'y avait rien dans le cache, donc je suppose qu'il ne répertorie pas le répertoire mais se base sur une sorte d'index ailleurs.
Tensibai
@Tensibai mais la configuration cmd npm get cache renvoie /home/jenkins.npm comme ce chemin ne pensez-vous pas que cela confirme l'emplacement du cache?
Brian Ogden
L'emplacement du cache oui, cela n'impose pas l'index du cache se trouve du tout au même emplacement. J'ajouterais un npm cache lset un brut ls ~/.npm/* -aldans le script de build lui-même avant toute autre étape de build juste pour assurer l'état du conteneur au démarrage de la build.
Tensibai

Réponses:

5

J'ai finalement résolu cela en utilisant la mise en cache de la couche d'image Docker pour l'installation de npm, en suivant cette réponse

Cela signifie que j'ai déplacé l'installation npm hors de l'image esclave Docker et dans l'image réellement frontale, voici mon fichier Docker final qui met vraiment en cache l'installation npm entre les builds si package.config n'a pas de modifications:

FROM centos:7
MAINTAINER Brian Ogden

# Not currently being used but may come in handy
ARG ENVIRONMENT
ENV NODE_VERSION 6.11.1

RUN yum -y update && \
    yum clean all && \
    yum -y install http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm \
    yum -y makecache && \
    yum -y install nginx-1.12.0 wget

# Cleanup some default NGINX configuration files we don’t need
RUN rm /etc/nginx/conf.d/default.conf

#############################################
# NodeJs Install
#############################################

#Download NodeJs package
RUN wget -q -O - https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz \
    | tar --strip-components=1 -xzf - -C /usr/local

# /programming//a/35774741/1258525
# use changes to package.json to force Docker not to use the cache
# when we change our application's nodejs dependencies:
COPY ./package.json /tmp/package.json
RUN cd /tmp && npm install
RUN mkdir /app && cp -a /tmp/node_modules /app/

WORKDIR /app
COPY . /app

RUN npm run build-$ENVIRONMENT

RUN cd /app && cp -a dist/* /usr/share/nginx/html
COPY ./docker/conf/frontend.conf /etc/nginx/conf.d/frontend.conf
COPY ./docker/conf/nginx.conf /etc/nginx/nginx.conf


EXPOSE 80

CMD ["nginx"]
Brian Ogden
la source
2
cela ne résout pas le problème décrit dans les questions. C'est juste une autre façon de mettre en cache. Connaissez-vous encore la raison? @Brian
An Nguyen
@AnNguyen non, et j'ai passé beaucoup de temps à essayer de faire fonctionner le cache npm. Je vous suggère d'utiliser ma solution
Brian Ogden
ma situation est différente. Chaque fois qu'une build est déclenchée, un esclave est provisionné sur k8s. Je ne peux donc pas mettre en cache basé sur le processus de construction de docker. Je veux me baser sur le cache NPM pour pouvoir monter un volume persistant dans l'esclave à chaque fois qu'il est provisionné
An Nguyen
0

Une autre approche que vous pouvez faire est de configurer un serveur de référentiel nexus où vous hébergez vos modules npm et proxy ceux externes. Il ne tire pas parti du cache, mais comme les ressources se trouvent dans votre réseau local ou peut-être dans le même essaim, cela ne devrait pas prendre autant de temps.

Archimedes Trajano
la source