Npm установка завершается неудачей в проекте jenkins в докере
Я следую учебному пособию о конвейере Jenkins, и я могу получить "привет мир", работающий в док-контейнере узла 6.10.
Но когда я добавил в репозиторий приложение EmberJS по умолчанию (с помощью ember init
) и попытался создать его в конвейере, оно перестало работать при запуске npm install (из-за проблем с доступом к каталогу). Файл Jenkins можно увидеть здесь: https://github.com/CloudTrap/pipeline-tutorial/blob/fix-build/Jenkinsfile
Сообщение об ошибке, напечатанное сборкой, (которое устанавливается локально и запускается с помощью java -jar jenkins.war
на Macbook, не имеет значения, но включено на всякий случай):
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.
Примечание: я бы не хотел запускать npm install
от имени пользователя root/sudo.
ОБНОВЛЕНИЕ: я был в состоянии сделать некоторый прогресс следующим образом:
Я нашел команду, которую Дженкинс использует для построения с использованием контейнера из журналов:
[Pipeline] withDockerContainer
$ docker run -t -d -u 501:20 -w /long-workspace-directory -v /long-workspace-directory:/long-workspace-directory:rw -v /[email protected]:/[email protected]:rw -e
Таким образом, когда запускается образ докера, его рабочий каталог представляет собой каталог /long-workspace-directory
(это действительно загадочно выглядящий путь рабочей области jenkins), а идентификатор пользователя - 501 (идентификатор группы 20) и т.д. У пользователя нет имени (что явно нарушает другие вещи, не связанные с этим вопросом).
-
Изменен агент для использования Dockefile:
agent {
dockerfile {
filename 'Dockerfile'
args '-v /.cache/ -v /.bower/ -v /.config/configstore/'
}
}
-
Укажите args '-v...'
для создания томов для каталогов, необходимых для npm install/bower.
Ответы
Ответ 1
из 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
}
}
Ответ 2
Впустую целый день по этой проблеме, я просто добавил следующее как переменную среды на этапе агента, используя Редактор конвейера, устранил проблему.
'npm_config_cache=npm-cache'
Ответ 3
Добавление окружения и установка Home в '.' решает это, как показано ниже.
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"
}
}
}
}
Ответ 4
Я добавляю ту же проблему. Я решил использовать его с помощью пользователя 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"
}
}
}
Ответ 5
Вы можете переопределить пользователя, с которым Jenkins запускает контейнер докера, например, здесь я переопределяю с помощью корня (userid: groupid равен 0: 0):
docker {
image 'node:8'
args '-u 0:0'
}
Вы можете определить текущего пользователя в параметрах docker run
в выводе консоли.
Ответ 6
У нас была та же проблема, основной проблемой для нас было то, что пользователь в контейнере и пользователь, работающий с Jenkins node, имели разные UID.
После изменения UID + GID пользователя в контейнере (и изменения
владение домашним каталогом пользователей), чтобы соответствовать
пользователь, выполняющий build node npm, будет вести себя нормально.
Это также может произойти, если Home-Directory контейнера-пользователя не может быть записана.
Код в файле Docker:
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>
Когда рабочая область монтируется в контейнер, она уже будет принадлежать
UID. При запуске контейнера через Jenkinsfile UID и GID
пользователь контейнера автоматически устанавливается в соответствии со строковым блоком. Но домашний каталог будет по-прежнему иметь своего первоначального владельца.
Теперь node_modules будет помещен в текущий каталог.
Ответ 7
В моем случае проблема заключалась в том, что внутри контейнера я был пользователем jenkins вместо root. Я получил это, установив whoami
внутри контейнера, и получил ошибку, как будто cannot determine user 111
(который, как оказалось, является jenkins). Итак, я сделал следующее:
stage('Run build') {
webappImage.inside("-u root") {
sh "yarn run build"
}
}
Ответ 8
Хотел просто предоставить немного больше деталей, короче говоря, принятый ответ работает, но я новичок в Docker и хотел получить лучшее понимание и решил, что поделюсь тем, что нашел.
Так что для нашей установки jenkins, она запускает контейнеры через
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 работать правильно, мы просто указываем переменную окружения HOME для пользователя на текущую папку через файл Jenkins.
pipeline {
agent none
stages {
stage('NPM Installs') {
agent {
docker {
image 'circleci/node:latest'
}
}
environment { HOME="." }
...
}
}
}
Таким образом, давая пользователю возможность создать необходимую .npm
папку в /folder/forProject/.npm
Надеюсь, это кому-нибудь пригодится, и если вы видите что-то, что я ошибся, пожалуйста, дайте мне знать: D
Ответ 9
Вы можете установить 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
Ответ 10
эта конфигурация работает для меня.
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'
}
}
}
}