Jenkins:"sh npm i ..." 不在 docker 代理中工作

Jenkins: "sh npm i ..." not working in docker agent

意图

我正在尝试构建一个基于最新 node docker 图像的非常简单的声明 Jenkinsfile。我想通过在 Jenkinsfile 中调用 sh 'npm install ...' 来安装 Node.js 应用程序的依赖项。在没有 Jenkins 的情况下从 Docker 容器使用 npm 安装就像一个魅力,但在使用 Jenkins 管道时不是。

詹金斯文件

pipeline {
   agent { 
       docker {
           image 'node:latest'
       }
   }
   stages {
      stage('Install Dependencies') {
         steps {
            sh 'npm -v' // sanity check
            sh 'ls -lart' // debugging filesystem
            sh 'npm i axios' // this leads to the error
         }
      }
   }
}

控制台登录 Jenkins

+ npm install axios
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /.npm
npm ERR! errno -13
npm ERR! 
npm ERR! Your cache folder contains root-owned files, due to a bug in
npm ERR! previous versions of npm which has since been addressed.
npm ERR! 
npm ERR! To permanently fix this problem, please run:
npm ERR!   sudo chown -R 1962192188:58041779 "/.npm"

我假设它必须对来自 Jenkins and/or 的已安装卷中的特权做一些事情 Docker 容器 ist 的启动用户:

我试过的

  1. args '-u root' 在 Jenkinsfile 的 Docker 代码块中。这行得通,但我怀疑这应该如何解决。

    docker {
        image 'node:latest'
        args '-u root'
    }
    
  2. sudo chown -R 1962192188:58041779 "/.npm" 如错误消息中所建议的那样。但这会导致:

    + sudo chown -R 1962192188:58041779 /.npm
    /Users/<user>/.jenkins/workspace/pipe@tmp/durable-664f481d/script.sh: 1: 
    /Users/<user>/.jenkins/workspace/pipe@tmp/durable-664f481d/script.sh: sudo: not found
    
  3. Dockerfile中定义一个图层RUN npm install axios。这行得通,但出于好奇,我想知道为什么我不能直接在 Jenkinsfile 中调用它。

    FROM node:latest
    
    RUN npm i axios
    

解决此问题的最佳方法是使用以下方法之一(受 npm install fails in jenkins pipeline in docker 启发)。这三个最终都会将 .npm 的默认目录(即 npm 的缓存)更改为当前工作目录(这是映射到 Docker 容器的 Jenkins 作业的工作区)。

将 ENV 变量 HOME 设置为当前工作目录

声明式管道

pipeline {
    agent { docker { image 'node:latest'' } }
    environment {
        HOME = '.'
    }
    ...

脚本化管道

docker.image('node:latest').inside {
    withEnv([
        'HOME=.',
    ])
    ...

调用 npm install

时使用附加参数 --cache 更改 .npm 文件夹的位置
npm install --cache npm_cache <optional:packagename>

调用前设置npm使用的环境变量npm_config_cachenpm install

声明式管道

pipeline {
    agent { docker { image 'node:latest'' } }
    environment {
        npm_config_cache = 'npm-cache'
    }
    ...

脚本化管道

docker.image('node:latest').inside {
    withEnv([
        'npm_config_cache=npm-cache',
    ])
    ...

在尝试了很多东西之后,这对我有用。 Jenkins 似乎会将工作区目录映射到 docker 容器。

pipeline {
    agent { dockerfile true }
    environment {
        HOME = "${env.WORKSPACE}"
    }
...