如何让npm使用caching

好的,我应该添加一个警告,我在一个Docker容器中,但实际上应该不会有太大的关系,我不停止容器,并且为npmcaching文件夹以及/ home文件夹用户运行npm命令。

Docker容器的目的是安装npm,它是一个构build从站,由Jenkins构build起来构build一个AngularJs应用程序。 问题是,它非常慢,每次都下载所有需要的npm包。

jenkins是用户,build立服务器上的jenkins帐户是“谁”运行npm install

对于运行npm install cmd: /home/jenkins/.npm的用户,以及命令npm config get cache所说的文件夹,我的卷都是我的caching目录: /root/.npm 。 不是容器卷应该甚至重要,因为在运行npm install之后我还没有停止容器。

确定我开始debugging的步骤,开始,我用这个命令“打开容器”:

 docker exec -it <container_id> bash 

我从这个点运行的所有命令我连接到正在运行的容器与npm安装。

echo "$HOME"结果在/root

npm config get cacheroot/.npm npm config get cache结果

任何时候jenkins运行npm install在这个容器中,在那个命令成功完成之后,我运行npm cache ls ,总是产生空的,没有任何caching: ~/.npm

许多软件包被下载,但我们可以用ls -a /home/jenkins/.npm/看到: 在这里输入图像说明

所以我试着把cache-min设置为很长的到期时间: npm config set cache-min 9999999没有帮助。

我不知道还有什么可以做,看来我的npm软件包没有被caching,如何获得npm来caching软件包?

这里是一个截断的npm安装输出:

 Downloading binary from https://github.com/sass/node-sass/releases/download/v4.5.3/linux-x64-48_binding.node Download complete Binary saved to /home/jenkins/workspace/tsl.frontend.development/node_modules/node-sass/vendor/linux-x64-48/binding.node Caching binary to /home/jenkins/.npm/node-sass/4.5.3/linux-x64-48_binding.node Binary found at /home/jenkins/workspace/tsl.frontend.development/node_modules/node-sass/vendor/linux-x64-48/binding.node Testing binary Binary is fine typings WARN deprecated 3/24/2017: "registry:dt/core-js#0.9.7+20161130133742" is deprecated (updated, replaced or removed) [?25h +-- app (global) `-- core-js (global) 

这里是我的Dockerfile:

 FROM centos:7 MAINTAINER Brian Ogden RUN yum update -y && \ yum clean all ############################################# # Jenkins Slave setup ############################################# RUN yum install -y \ git \ openssh-server \ java-1.8.0-openjdk \ sudo \ make && \ yum clean all # gen dummy keys, centos doesn't autogen them like ubuntu does RUN /usr/bin/ssh-keygen -A # Set SSH Configuration to allow remote logins without /proc write access RUN sed -ri 's/^session\s+required\s+pam_loginuid.so$/session optional pam_loginuid.so/' /etc/pam.d/sshd # Create Jenkins User RUN useradd jenkins -m -s /bin/bash # Add public key for Jenkins login RUN mkdir /home/jenkins/.ssh COPY /files/id_rsa.pub /home/jenkins/.ssh/authorized_keys #setup permissions for the new folders and files RUN chown -R jenkins /home/jenkins RUN chgrp -R jenkins /home/jenkins RUN chmod 600 /home/jenkins/.ssh/authorized_keys RUN chmod 700 /home/jenkins/.ssh # Add the jenkins user to sudoers RUN echo "jenkins ALL=(ALL) ALL" >> etc/sudoers ############################################# # Expose SSH port and run SSHD EXPOSE 22 #Technically, the Docker Plugin enforces this call when it starts containers by overriding the entry command. #I place this here because I want this build slave to run locally as it would if it was started in the build farm. CMD ["/usr/sbin/sshd","-D"] ############################################# # Docker and Docker Compose Install ############################################# #install required packages RUN yum install -y \ yum-utils \ device-mapper-persistent-data \ lvm2 \ curl && \ yum clean all #add Docker CE stable repository RUN yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo #Update the yum package index. RUN yum makecache fast #install Docker CE RUN yum install -y docker-ce-17.06.0.ce-1.el7.centos #install Docker Compose 1.14.0 #download Docker Compose binary from github repo RUN curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose #Apply executable permissions to the binary RUN chmod +x /usr/local/bin/docker-compose ############################################# ENV NODE_VERSION 6.11.1 ############################################# # NodeJs Install ############################################# RUN yum install -y \ wget #Download NodeJs package RUN wget https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz #extract the binary package into our system's local package hierarchy with the tar command. #The archive is packaged within a versioned directory, which we can get rid of by passing the --strip-components 1 option. #We will specify the target directory of our command with the -C command: #This will install all of the components within the /usr/local branch RUN tar --strip-components 1 -xzvf node-v* -C /usr/local ############################################# ############################################# # npm -setup volume for package cache # this will speed up builds ############################################# RUN mkdir /home/jenkins/.npm RUN chown jenkins /home/jenkins/.npm . RUN mkdir /root/.npm RUN chown jenkins /root/.npm . #for npm cache, this cannot be expressed in docker-compose.yml #the reason for this is that Jenkins spins up slave containers using #the docker plugin, this means that there VOLUME /home/jenkins/.npm VOLUME /root/.npm ############################################# 

当你运行docker exec -it <container> bash你以root用户的身份访问Docker容器。 npm install从而将caching保存到/root/.npm ,这不是容器保存的卷。 另一方面,Jenkins使用jenkins用户,该用户保存到正在被caching的/home/jenkins/.npm 。 因此,为了模拟Jenkins工作stream程的function,你需要先npm install su jenkins然后才能npm install

这就是说,npmcaching不是一个完美的解决scheme(特别是如果你有一个自动化的Jenkins构build)。 有些事情要研究,这将是更好的长期解决scheme:

  • 安装像sinopia这样的本地NPM Cache。 我发现这个指南特别有用。

  • 使用Docker来构build你的应用程序(这将在Docker中使用Docker工作)。 Docker会在每个构build步骤之后caching,从而节省重复的依赖关系。