私はJenkinsパイプラインに関するチュートリアルに従っています。ノード6.10のdocker containerで「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.
注:npm install
をルート/ Sudoとしてnot実行したいと思います。
更新:私は次のようにいくつかの進歩を遂げることができました:
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
(実際には不可解なジェンキンスワークスペースパス)であり、ユーザーIDは501(グループID 20)などです。ユーザーには名前がありません(これは明らかにこの質問に関係のない他のものを壊している)。
Dockefileを使用するようにエージェントを変更しました:
agent {
dockerfile {
filename 'Dockerfile'
args '-v /.cache/ -v /.bower/ -v /.config/configstore/'
}
}
Npm install/bowerが必要とするディレクトリのボリュームを作成するには、args '-v ...'
を指定します。
から 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
}
}
環境を追加し、ホームを「。」に設定しますこれを以下のように解決します。
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"
}
}
}
}
この問題で1日を無駄にした後、Pipeline Editorを使用してエージェント段階で環境変数として次を追加するだけで問題が解決することがわかりました。
'npm_config_cache=npm-cache'
少しだけ詳細を提供したかった、要するに受け入れられた答えは機能しますが、私は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を正しく機能させるには、ユーザーのコンテナーのHOME環境変数をJenkinsファイル経由で現在のフォルダーにポイントするだけです。
pipeline {
agent none
stages {
stage('NPM Installs') {
agent {
docker {
image 'circleci/node:latest'
}
}
environment { HOME="." }
...
}
}
}
したがって、ユーザーに必要な.npm
フォルダー/folder/forProject/.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コンテナを実行するユーザーをオーバーライドできます。たとえば、ここではルート(userid:groupidは0:0)でオーバーライドします。
docker {
image 'node:8'
args '-u 0:0'
}
コンソール出力のdocker run
パラメーターで現在のユーザーを見つけることができます。
この設定は私のために機能します。
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'
}
}
}
}
私の場合、問題はコンテナ内でrootではなくユーザーjenkinsだったことです。コンテナ内にwhoami
を設定してそこにたどり着きましたが、cannot determine user 111
(たまたまジェンキンです)。だから私は次のことをしました:
stage('Run build') {
webappImage.inside("-u root") {
sh "yarn run build"
}
}
コンテナ内のユーザーとJenkinsノードを実行しているユーザーのUIDが異なるという同じ問題がありました。コンテナ内のユーザーのUID + GIDを変更(およびユーザーのホームディレクトリの所有権を変更)した後、ビルドノードnpmを実行しているユーザーと一致するようになりました。
これは、container-userのHome-Directoryが書き込み可能でない場合にも発生する可能性があります。
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>
ワークスペースはコンテナにマウントされるため、すでにUIDに属します。 Jenkinsfileを介してコンテナを実行すると、コンテナユーザーのUIDとGIDがビルドノードに一致するように自動的に設定されます。ただし、ホームディレクトリには元の所有者が残ります。
これで、node_modulesは現在のディレクトリに配置されます。
グローバルな依存関係として設定することなく、ビルド前に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