簡體   English   中英

npm install 在 docker 的 jenkins 管道中失敗

[英]npm install fails in jenkins pipeline in docker

我正在關注關於 Jenkins 管道的教程,我可以在節點 6.10 docker 容器下獲得一個“hello world”。

但是,當我將默認的 EmberJS 應用程序(使用ember init )添加到存儲庫並嘗試在管道中構建它時,運行 npm install 時它會失敗(因為目錄訪問問題)。 Jenkinsfile 可以在這里看到: https ://github.com/CloudTrap/pipeline-tutorial/blob/fix-build/Jenkinsfile

構建打印的錯誤消息是(在本地安裝並在 Macbook 上使用java -jar jenkins.war運行,不相關但以防萬一)是:

npm ERR! Linux 4.9.12-moby
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install"
npm ERR! node v6.10.0
npm ERR! npm  v3.10.10
npm ERR! path /.npm
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall mkdir

npm ERR! Error: EACCES: permission denied, mkdir '/.npm'
npm ERR!     at Error (native)
npm ERR!  { Error: EACCES: permission denied, mkdir '/.npm'
npm ERR!     at Error (native)
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: '/.npm',
npm ERR!   parent: 'pipeline-tutorial' }
npm ERR! 
npm ERR! Please try running this command again as root/Administrator.

注意:我不想以 root / sudo 身份運行npm install

更新:我已經取得了一些進展,如下所示:

我從日志中找到了 Jenkins 使用容器構建的命令:

[Pipeline] withDockerContainer
$ docker run -t -d -u 501:20 -w /long-workspace-directory -v /long-workspace-directory:/long-workspace-directory:rw -v /long-workspace-directory@tmp:/long-workspace-directory@tmp:rw -e

因此,當 docker 映像運行時,它的工作目錄是/long-workspace-directory (它實際上是一個看起來很神秘的 jenkins 工作區路徑),用戶 id 是 501(組 id 20)等。用戶沒有名字(這顯然破壞了與這個問題無關的其他事情)。

  1. 更改代理以使用 Dockefile:

     agent { dockerfile { filename 'Dockerfile' args '-v /.cache/ -v /.bower/ -v /.config/configstore/' } }
  2. 指定args '-v ...'為 npm install / bower 需要的目錄創建卷。

添加環境並將主頁設置為“。” 解決這個問題如下。

pipeline {
    agent { docker { image 'node:8.12.0' } }
    environment {
        HOME = '.'
    }
    stages {
        stage('Clone') {
            steps {
                git branch: 'master',
                    credentialsId: '121231k3jkj2kjkjk',
                    url: 'https://myserver.com/my-repo.git'
            }
        }
        stage('Build') {
            steps {
                sh "npm install"
            }
        }
    }
}

來自https://github.com/jenkins-infra/jenkins.io/blob/master/Jenkinsfile

docker.image('openjdk:8').inside {
    /* One Weird Trick(tm) to allow git(1) to clone inside of a
    * container
    */
    withEnv([
        /* Override the npm cache directory to avoid: EACCES: permission denied, mkdir '/.npm' */
        'npm_config_cache=npm-cache',
        /* set home to our current directory because other bower
        * nonsense breaks with HOME=/, e.g.:
        * EACCES: permission denied, mkdir '/.config'
        */
        'HOME=.',
    ]) {
            // your code
    }
}

在這個問題上浪費了一整天,我發現只需在代理階段使用管道編輯器添加以下內容作為環境變量就可以解決問題。

'npm_config_cache=npm-cache'

當 Jenkins 在 Docker 代理中運行階段時,它通常設置HOME=/ (圖像WORKDIR值),但是 Jenkins 用戶在該目錄中沒有寫入權限,這就是npm無法創建其緩存目錄~/.npm的原因。 要解決這個問題,您需要覆蓋HOME或 NPM 默認緩存目錄:

pipeline {
    agent {
        docker {
            reuseNode true
            image 'node:16.15'
        }
    }

    environment {
        // Override HOME to WORKSPACE
        HOME = "${WORKSPACE}"
        // or override default cache directory (~/.npm)
        NPM_CONFIG_CACHE = "${WORKSPACE}/.npm"
    }

    stages {
        stage('Build') {
            steps {
                sh 'npm install'
                sh 'npm run build'
            }
        }
    }
}

只想提供更多細節,簡而言之,接受的答案有效,但我是 Docker 新手,想要更好地理解並想分享我發現的東西。

所以對於我們的詹金斯設置,它通過以下方式啟動容器

docker run -t -d -u 995:315 -w /folder/forProject -v /folder/forProject:/folder/forProject:rw,z ...

結果,該容器以用戶身份運行uid=995 gid=315 groups=315

由於我使用的映像 (circleci/node:latest) 沒有具有此 UID/GID 的用戶,因此該用戶將沒有“主”文件夾,並且僅對已安裝的卷具有權限。

當調用 NPM 命令時,它將嘗試使用該用戶的主目錄(用於緩存),並且由於該用戶不是在映像上創建的,因此主目錄設置為/ (Linux 的默認值?)。 因此,為了讓 NPM 正常工作,我們只需通過 Jenkins 文件將用戶的容器 HOME 環境變量指向當前文件夾

pipeline {
  agent none
  stages {
    stage('NPM Installs') {
      agent {
        docker {
            image 'circleci/node:latest'
        }
      }
      environment { HOME="." }
      ...
    }
  }
}

從而使用戶能夠在/folder/forProject/.npm中創建所需的.npm文件夾

希望這對某人有幫助,如果您發現我做錯了什么,請告訴我:D

我添加了同樣的問題。 我使用root用戶運行Docker鏡像解決了它:

node {
    stage("Prepare environment") {
        checkout scm
        // Build the Docker image from the Dockerfile located at the root of the project
        docker.build("${JOB_NAME}")
    }

    stage("Install dependencies") {
        // Run the container as `root` user
        // Note: you can run any official Docker image here
        withDockerContainer(args: "-u root", image: "${JOB_NAME}") {
            sh "npm install"
        }
    }
}

您可以覆蓋 Jenkins 運行 docker 容器的用戶,例如這里我用 root 覆蓋(userid:groupid 為 0:0):

docker { 
    image 'node:8'
    args '-u 0:0'
}

您可以在控制台輸出的docker run參數中發現當前用戶。

我們有同樣的問題,對我們來說問題的核心是,容器中的用戶和運行 Jenkins 節點的用戶有不同的 UID。 在更改容器中用戶的 UID+GID(並更改用戶主目錄的所有權)以匹配運行構建節點的用戶之后,npm 將表現正常。

如果容器用戶的主目錄不可寫,也可能發生這種情況。

Dockerfile 中的代碼:

RUN usermod -u <uid of buildnode> <container user> && \
    groupmod -g <gid of buildnode> <container user group> && \
    chown -R <container user>:<container user group> /home/<container user>

由於 Workspace 已安裝到容器中,因此它已經屬於 UID。 當通過 Jenkinsfile 運行容器時,容器用戶的 UID 和 GID 會自動設置為與 buildnode 匹配。 但主目錄仍將擁有其原始所有者。

現在 node_modules 將被放置在當前目錄中。

就我而言,問題是在容器內我是用戶 jenkins 而不是 root。 我通過在容器內設置whoami到達那里並得到了cannot determine user 111 (恰好是詹金斯)之類的錯誤。 所以我做了以下事情:

stage('Run build') {
        webappImage.inside("-u root") {
            sh "yarn run build"
        }
    }

這個配置對我有用。

pipeline {
    agent {
        docker {
            image 'node:6-alpine'
            args '-p 3000:3000 -p 5000:5000'
            args '-u 0:0'

        }
    }
    environment {
        CI = 'true'
    }
    stages {
        stage('Build') {
            steps {
                sh 'npm install --unsafe-perm'
            }
        }
        stage('Test') {
            steps {
                sh './jenkins/scripts/test.sh'
            }
        }
        stage('Deliver for development') {
            when {
                branch 'development' 
            }
            steps {
                sh './jenkins/scripts/deliver-for-development.sh'
                input message: 'Finished using the web site? (Click "Proceed" to continue)'
                sh './jenkins/scripts/kill.sh'
            }
        }
        stage('Deploy for production') {
            when {
                branch 'production'  
            }
            steps {
                sh './jenkins/scripts/deploy-for-production.sh'
                input message: 'Finished using the web site? (Click "Proceed" to continue)'
                sh './jenkins/scripts/kill.sh'
            }
        }
    }
}

就我而言,這解決了問題

            agent {
                docker {
                    image 'node:10-stretch'
                    args '-v /home/jenkins/.ssh:/home/jenkins/.ssh:ro -u 0'
                }
            }

我正在使用 maven 構建項目,它確實正在運行負責調用 npm install 的前端 maven-plugin 所以 npm install 因錯誤而中斷:path /.npm npm ERR! 代碼 EACCES npm 錯誤! errno -13 npm 錯誤! 系統調用 mkdir

我將其更改為npm install --cache /tmp/empty-cache

它奏效了

您可以在構建之前即時安裝nvm ,在具有NVM_DIR的本地目錄中,無需將其設置為全局依賴項:

mkdir -p node_dir
export NVM_DIR=$(pwd)/node_dir
curl https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash
source $(pwd)/node_dir/nvm.sh
nvm install 7
nvm use 7

新地點是:

$ which node
~/someDir/node_dir/versions/node/v7.7.2/bin/node

$ which npm
~/someDir/node_dir/versions/node/v7.7.2/bin/npm

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM