Je suis un tutoriel sur le pipeline Jenkins et je peux obtenir un "hello world" dans le conteneur 6.10 du noeud dock.
Mais, lorsque j'ai ajouté une application EmberJS par défaut (à l'aide de ember init
) au référentiel et que je tentais de la construire dans le pipeline, elle échouait lors de l'exécution de npm install (en raison de problèmes d'accès au répertoire). Le Jenkinsfile peut être vu ici: https://github.com/CloudTrap/pipeline-tutorial/blob/fix-build/Jenkinsfile
Le message d'erreur imprimé par la construction est (installé localement et exécuté à l'aide de Java -jar jenkins.war
sur un Macbook, non pertinent mais inclus uniquement dans le cas où):
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.
Remarque: je voudrais pas exécuter npm install
en tant que root/Sudo.
MISE À JOUR: J'ai pu faire des progrès comme suit:
J'ai trouvé la commande que Jenkins utilise pour construire en utilisant le conteneur à partir des journaux:
[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
Ainsi, lorsque l’image de docker est exécutée, son répertoire de travail est un /long-workspace-directory
(c’est vraiment un chemin d’espace de travail jenkins crypté) et son identifiant d’utilisateur est 501 (identifiant de groupe 20), etc. L’utilisateur n’a pas de nom (qui est apparemment en train de autres choses non liées à cette question).
Agent modifié pour utiliser un fichier Dock:
agent {
dockerfile {
filename 'Dockerfile'
args '-v /.cache/ -v /.bower/ -v /.config/configstore/'
}
}
Spécifiez args '-v ...'
pour créer des volumes pour les répertoires dont npm install/bower a besoin.
de 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
}
}
Après avoir passé une journée entière sur cette question, j'ai constaté que l'ajout du texte suivant en tant que variable d'environnement au stade de l'agent à l'aide de l'éditeur de pipeline a résolu le problème.
'npm_config_cache=npm-cache'
Ajout des environnements et configuration de la maison sur '.' résout cela comme ci-dessous.
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"
}
}
}
}
J'ajoute le même problème. Je l'ai résolu en utilisant l'utilisateur root
pour exécuter l'image 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"
}
}
}
Dans mon cas, le problème était que dans le conteneur, j’étais l’utilisateur jenkins au lieu de root. J'y suis arrivé en mettant whoami
à l'intérieur du conteneur et j'ai une erreur comme cannot determine user 111
(qui se trouve être jenkins). Alors j'ai fait ce qui suit:
stage('Run build') {
webappImage.inside("-u root") {
sh "yarn run build"
}
}
Je voulais juste fournir un peu plus de détails. En bref, la réponse acceptée fonctionne, mais je suis nouvelle à Docker et je voulais obtenir une meilleure compréhension. Je me suis dit que je partagerais ce que j'ai trouvé.
Donc, pour notre configuration Jenkins, il commence les conteneurs via
docker run -t -d -u 995:315 -w /folder/forProject -v /folder/forProject:/folder/forProject:rw,z ...
Par conséquent, ce conteneur s'exécute en tant qu'utilisateur uid=995 gid=315 groups=315
Comme l’image que j’utilisais (circleci/node: latest) n’a pas d’utilisateur avec cet UID/GID, l’utilisateur ne disposera pas d’un dossier «home» et n’aura la permission que sur le volume monté.
Lorsque les commandes NPM sont appelées, il essaie d’utiliser le répertoire de base de cet utilisateur (pour le cache) et, comme cet utilisateur n’a pas été créé sur l’image, le répertoire de base est défini sur /
(valeur par défaut pour Linux?). Donc, pour que NPM fonctionne correctement, il suffit de pointer la variable d’environnement HOME des conteneurs de l’utilisateur vers le dossier actuel via le fichier Jenkins.
pipeline {
agent none
stages {
stage('NPM Installs') {
agent {
docker {
image 'circleci/node:latest'
}
}
environment { HOME="." }
...
}
}
}
Donnant ainsi à l'utilisateur la possibilité de créer le dossier .npm
requis dans /folder/forProject/.npm
J'espère que cela est utile à quelqu'un et si vous voyez quelque chose que je me suis trompé s'il vous plaît faites le moi savoir: D
Nous avions le même problème, le cœur du problème pour nous étant que l’utilisateur dans le conteneur et l’utilisateur exécutant le nœud Jenkins avaient des UID différents . Après avoir modifié les UID + GID de l’utilisateur dans le conteneur (et propriétaire du répertoire de base de l'utilisateur) correspondant à l'utilisateur exécutant le noeud de génération npm se comporterait normalement.
Cela peut également se produire si le répertoire de base de l'utilisateur du conteneur n'est pas accessible en écriture.
Code dans le fichier 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>
Au fur et à mesure que l'espace de travail est monté dans le conteneur, il appartiendra déjà à l'UID Lors de l'exécution du conteneur via le fichier Jenkins, les UID et GID de L'utilisateur du conteneur sont automatiquement configurés pour correspondre au buildnode. Mais le répertoire personnel aura toujours son propriétaire d'origine.
Maintenant, les node_modules seront placés dans le répertoire actuel.
Vous pouvez remplacer l'utilisateur avec lequel Jenkins exécute le conteneur Docker, par exemple, ici, je remplace par la racine (ID utilisateur: ID groupe: 0: 0):
docker {
image 'node:8'
args '-u 0:0'
}
Vous pouvez repérer l'utilisateur actuel dans les paramètres docker run
de la sortie de la console.
Vous pouvez installer nvm
à la volée avant de construire, dans un répertoire local avec NVM_DIR
sans le définir comme dépendance globale:
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
Les nouveaux emplacements sont:
$ which node
~/someDir/node_dir/versions/node/v7.7.2/bin/node
$ which npm
~/someDir/node_dir/versions/node/v7.7.2/bin/npm