如何让 npm 使用缓存

Bri*_*den 6 caching node.js npm docker

更新

我改变了这个问题的方向,最终利用 Docker 镜像层来缓存 npm 安装,除非 package.config 有更改,请参见此处

请注意,关于这个问题,我仍然在从属 Jenkins Docker 映像中构建我的 AngularJs Docker 映像,但我不再在 Docker 从属中运行 npm install,我将我的应用程序文件复制到我的 AngularJs Docker 映像并运行 npm install AngularJs Docker 映像,从而获得 npm 安装的 Docker 缓存层,灵感来自这里的这个好主意/答案

-------------------------------END 更新----------------- -------------

好的,我应该添加一个警告,即我在 Docker 容器中,但这实际上并不重要,我不会停止容器,并且我有用于 npm 缓存文件夹的卷以及用于运行 npm 命令的用户。

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

jenkins 是用户,构建服务器上的 jenkins 帐户是“正在运行的人” npm install

我有运行npm installcmd:的用户的 npm 文件夹/home/jenkins/.npm和命令npm config get cache所说的文件夹是我的缓存目录:的卷/root/.npm。并不是说容器卷应该重要,因为我在运行npm install.

好的,我开始调试所采取的步骤,首先,我使用以下命令“进入容器”:

docker exec -it <container_id> bash
Run Code Online (Sandbox Code Playgroud)

我从现在开始运行的所有命令都连接到安装了 npm 的正在运行的容器。

echo "$HOME" 结果是 /root

npm config get cache 结果是 root/.npm

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

然而,正如我们所看到的,许多软件包都被下载了ls -a /home/jenkins/.npm/在此处输入图片说明

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

我不知道还能做什么,似乎我的 npm 包都没有被缓存,我如何让 npm 缓存包?

这是一个截断的 npm install 输出:

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)
Run Code Online (Sandbox Code Playgroud)

这是我的 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
#############################################
Run Code Online (Sandbox Code Playgroud)

Der*_*own 5

当您运行时,docker exec -it <container> bash您以root用户身份访问 Docker 容器。npm install因此将缓存保存到/root/.npm,这不是容器保存的卷。另一方面,Jenkins 使用jenkins保存到的用户,该用户/home/jenkins/.npm被缓存。因此,为了模拟实际 Jenkins 工作流程的功能,您需要su jenkinsnpm install.

话虽如此,npm 缓存并不是一个完美的解决方案(特别是如果你有大量的自动化 Jenkins 构建)。一些需要研究的事情将是更好的长期解决方案:

  • 安装本地 NPM 缓存,如sinopia. 我发现本指南特别有用。

  • 使用 Docker 构建您的应用程序(在 Docker 中使用 Docker 可以很好地工作)。Docker 会在每个构建步骤之后进行缓存,从而避免重复获取依赖项。