npm install fails in jenkins pipeline in docker

Solution 1:

Adding the environments and setting the Home to '.' solves this as below.

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"
            }
        }
    }
}

Solution 2:

from 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
    }
}

Solution 3:

Having wasted a whole day on this issue, I found simply adding the following as an environment variable at the agent stage using the Pipeline Editor removed the problem.

'npm_config_cache=npm-cache'

Solution 4:

When Jenkins runs the stage in Docker agent it usually sets HOME=/ (image WORKDIR value), but Jenkins user does not have write permissions in this directory, that's why npm cannot create its cache directory ~/.npm. To solve this you need either to override HOME or NPM default cache directory:

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

Solution 5:

Wanted to just provide a bit more detail, in short the accepted answer works but that I'm new to Docker and wanted to get a better understanding and figured i'd share what i found.

So for our jenkins setup, it starts containers via

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

As a result this container is running as user uid=995 gid=315 groups=315

Since the image I was using (circleci/node:latest) doesn’t have a user with this UID/GID, the user will not have a “home” folder and will only have permission on the mounted volume.

When NPM commands are called it will try using that users home directory (for cache) and since that user wasn’t created on the image, the home directory gets set to / (default for linux?). So to get NPM to work correctly we simply point the containers HOME environment variable for the user to the current folder via the Jenkins file

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

Thus giving the user the ability to create the required .npm folder in /folder/forProject/.npm

Hopefully this is helpful to someone and if you see something that i got wrong please let me know :D