docker - la instalación de npm falla en la tubería jenkins en la ventana acoplable
ember.js jenkins-pipeline (9)
Añadiendo los entornos y configurando el Inicio en ''.'' resuelve esto como abajo.
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"
}
}
}
}
Estoy siguiendo un tutorial sobre la tubería de Jenkins y puedo obtener un "hola mundo" trabajando en el nodo 6.10 contenedor de la ventana acoplable.
Pero, cuando agregué una aplicación EmberJS predeterminada (usando ember init
) al repositorio e intento construirlo en la tubería, falla cuando se ejecuta la instalación de npm (debido a problemas de acceso al directorio). El archivo Jenkins se puede ver aquí: https://github.com/CloudTrap/pipeline-tutorial/blob/fix-build/Jenkinsfile
El mensaje de error impreso por la compilación es (que se instala localmente y se ejecuta utilizando java -jar jenkins.war
en una Macbook, no es relevante pero se incluye en el caso):
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.
Nota: me gustaría no ejecutar npm install
como root / sudo.
ACTUALIZACIÓN: He podido hacer algunos progresos de la siguiente manera:
Encontré el comando que Jenkins usa para construir usando el contenedor de los registros:
[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
Por lo tanto, cuando la imagen de la ventana acoplable se ejecuta, su directorio de trabajo es un directorio /long-workspace-directory
(es realmente una ruta de espacio de trabajo de Jenkins con aspecto críptico) y la ID de usuario es 501 (ID de grupo 20), etc. El usuario no tiene un nombre (que aparentemente está rompiendo otras cosas no relacionadas con esta pregunta).
Agente cambiado para usar un Dockefile:
agent { dockerfile { filename ''Dockerfile'' args ''-v /.cache/ -v /.bower/ -v /.config/configstore/'' } }
Especifique
args ''-v ...''
para crear volúmenes para los directorios que npm install / bower needs.
Añado el mismo tema. Lo resolví usando el usuario root
para ejecutar la imagen de 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"
}
}
}
En mi caso, el problema era que dentro del contenedor yo era jenkins en lugar de root. Llegué allí estableciendo whoami
dentro del contenedor y obtuve un error, cannot determine user 111
(que resulta ser jenkins). Así que hice lo siguiente:
stage(''Run build'') {
webappImage.inside("-u root") {
sh "yarn run build"
}
}
Habiendo desperdiciado un día entero en este problema, encontré que simplemente agregar lo siguiente como una variable de entorno en la etapa de agente utilizando el Editor de tuberías eliminó el problema.
''npm_config_cache=npm-cache''
Puede anular el usuario con el que Jenkins ejecuta el contenedor de la ventana acoplable, por ejemplo, aquí anulo con la raíz (ID de usuario: groupid es 0: 0):
docker {
image ''node:8''
args ''-u 0:0''
}
Puede detectar al usuario actual en los parámetros de docker run
la docker run
en la salida de la consola.
Puede instalar nvm
sobre la marcha antes de construir, en un directorio local con NVM_DIR
sin configurarlo como dependencia global:
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
Las nuevas ubicaciones son:
$ which node
~/someDir/node_dir/versions/node/v7.7.2/bin/node
$ which npm
~/someDir/node_dir/versions/node/v7.7.2/bin/npm
Quería simplemente proporcionar un poco más de detalles, en resumen, la respuesta aceptada funciona, pero que soy nuevo en Docker y quería comprender mejor y pensé que compartiría lo que encontré.
Así que para nuestra configuración de Jenkins, se inicia contenedores a través de
docker run -t -d -u 995:315 -w /folder/forProject -v /folder/forProject:/folder/forProject:rw,z ...
Como resultado, este contenedor se ejecuta como usuario uid=995 gid=315 groups=315
Dado que la imagen que estaba usando (circleci / node: latest) no tiene un usuario con este UID / GID, el usuario no tendrá una carpeta "de inicio" y solo tendrá permiso en el volumen montado.
Cuando se llaman los comandos NPM, intentará usar el directorio de inicio de ese usuario (para caché) y dado que ese usuario no se creó en la imagen, el directorio de inicio se establece en /
(¿predeterminado para Linux?). Así que para que NPM funcione correctamente, simplemente apuntamos la variable de entorno HOME del contenedor para el usuario a la carpeta actual a través del archivo Jenkins
pipeline {
agent none
stages {
stage(''NPM Installs'') {
agent {
docker {
image ''circleci/node:latest''
}
}
environment { HOME="." }
...
}
}
}
De este modo, el usuario puede crear la carpeta .npm
requerida en /folder/forProject/.npm
Esperemos que esto sea útil para alguien y si ves algo que me equivoque, házmelo saber: D
Tuvimos el mismo problema, el núcleo del problema para nosotros fue que el usuario en el contenedor y el usuario que ejecuta el nodo de Jenkins tenían diferentes UID. Después de cambiar el UID + GID del usuario en el contenedor (y cambiar la propiedad del directorio de inicio de los usuarios) para que coincida con el usuario que ejecuta el nodo de compilación, npm se comportaría normalmente.
Esto también puede suceder si el directorio de inicio del usuario contenedor no se puede escribir.
Código en el 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>
Como el espacio de trabajo está montado en el contenedor, ya pertenecerá al UID. Cuando se ejecuta el contenedor a través del archivo Jenkins, el UID y el GID del usuario del contenedor se configuran automáticamente para coincidir con el buildnode. Pero el directorio de inicio todavía tendrá su propietario original.
Ahora los node_modules se colocarán en el directorio actual.
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
}
}