【问题标题】:How to get npm to use cache如何让 npm 使用缓存
【发布时间】:2018-04-05 22:38:13
【问题描述】:

更新

我改变了这个问题的方向,最终利用 Docker 映像层来缓存 npm 安装,除非 package.config see here 发生更改。

注意,关于这个问题,我仍然在从属 Jenkins Docker 映像中构建我的 AngularJs Docker 映像,但我不再在 Docker 从站中运行 npm install,我将我的应用程序文件复制到我的 AngularJs Docker 映像并运行npm install 在 AngularJs Docker 镜像中,从而获得 npm install 的 Docker 缓存层,灵感来自这个伟大的idea/answer here

-------------------结束更新------------- ----------------

好的,我应该补充一点,我在一个 Docker 容器中,但这可能并不重要,我不会停止容器,并且我有用于 npm 缓存文件夹和 /home 的卷运行 npm 命令的用户的文件夹。

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

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

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

好的,我开始调试的步骤,开始,我用这个命令“bash into the container”:

docker exec -it <container_id> bash

我从现在开始运行的所有命令都连接到安装了 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)

这是我的 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 容器中”是指使用docker rundocker exec 执行此操作吗?
  • 我只是 docker exec -it bash 进入容器运行 cmds
  • @DerekBrown 我更新了我的答案以详细说明这一点
  • 我能问一下为什么吗?这并不是 Docker 的真正预期功能......
  • @DerekBrown 缓存 npm 包不适合 Docker 吗?为什么这么说?

标签: node.js docker caching npm


【解决方案1】:

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

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

  • 安装本地 NPM 缓存,例如 sinopia。我发现this guide 特别有用。

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

【讨论】:

  • 谢谢,所以我们已经确定缓存确实在工作,至少根据 npm cache ls 是这样。虽然我必须承认,npm 似乎仍然没有将缓存用于任何事情,每个包都会进行 http 调用
  • @BrianOgden 您是否尝试过将此方法与您之前尝试过的cache min 相结合?
  • 你知道我用于 Docker 容器的卷是悬空的,成为孤立的,所以这是我要处理的下一个问题
猜你喜欢
  • 2021-05-16
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 2012-05-10
  • 1970-01-01
  • 2011-07-18
相关资源
最近更新 更多