Luego de de nuestra prolongada selección de información hemos podido resolver este contratiempo que presentan muchos usuarios. Te regalamos la solución y nuestro deseo es que sea de gran apoyo.
Solución:
Encontré una solución alternativa, consulte Local settings.xml no recogido por el agente de Jenkins:
El problema está relacionado con la
-u uid:gid
que jenkins usa para ejecutar el contenedor. Como sabrá, la imagen que está ejecutando solo tiene el usuarioroot
creado, por lo que cuando jenkins pasa su propio uid y gid, no hay ninguna entrada para el usuario y, en consecuencia, no$HOME
declarado por ello.Si solo desea ejecutar la compilación independientemente del usuario, puede usar lo siguiente como agente:
agent docker image 'maven:3-alpine' args '-v $HOME/.m2:/root/.m2:z -u root' reuseNode true
Algunas notas:
- si notas el volumen que estoy usando con la bandera
z
, ya que voy a compilar con root, necesito decirle a Docker que este volumen se compartirá entre otros contenedores y luego evitar el acceso denegado desde mi contenedor jenkins (ejecutándose con el usuario jenkins no root)- Le digo a jenkins que reuseNode, por lo que cualquier otra etapa que use la misma imagen se ejecutará en el mismo contenedor (es solo para acelerar el tiempo de aprovisionamiento)
Tronco
[DEBUG] Reading global settings from /usr/share/maven/conf/settings.xml
[DEBUG] Reading user settings from /root/.m2/settings.xml
[DEBUG] Reading global toolchains from /usr/share/maven/conf/toolchains.xml
[DEBUG] Reading user toolchains from /root/.m2/toolchains.xml
[DEBUG] Using local repository at /root/.m2/repository
[DEBUG] Using manager EnhancedLocalRepositoryManager with priority 10.0 for /root/.m2/repository
Desafortunadamente, los archivos en el repositorio local. /home/jenkins/.m2
ahora son propiedad del usuario root
en lugar de usuario jenkins
. Eso podría causar otros problemas.
Puedes ver mi respuesta relacionada pero usando la configuración de Gradle.
Como dijiste, en mi imagen base, Jenkins ejecuta el contenedor Docker con el usuario 1002 y no hay ningún usuario definido. Tienes que configurar la variable Maven user.home
para poner las dependencias allí. Puedes hacerlo incluyendo user.home
en el JAVA_OPTIONS
como una variable de entorno en su canalización. también MAVEN_CONFIG
debe incluirse:
environment
JAVA_TOOL_OPTIONS = '-Duser.home=/var/maven'
SETTINGS = credentials('your-secret-file')
y crea un volumen para almacenar en caché las dependencias:
docker
image 'maven:3.3.9-jdk-8-alpine'
args '-v $HOME:/var/maven'
reuseNode true
ACTUALIZAR: olvidé decirte que puedes poner tu settings.xml
en un archivo secreto con el fin de utilizar un “principio de mínima exposición” para limitar la exposición de las credenciales en la tubería de Jenkins. También estamos configurando credenciales personales y esta es la forma en que configuramos, por ejemplo, las credenciales de Nexus por usuario. Consulte la documentación de Jenkins sobre cómo cargar su archivo secreto en sus credenciales:
sh 'mvn -s $SETTINGS -B clean verify'
ACTUALIZAR2: No estoy usando una canalización declarativa, por lo que mi canalización se ve así:
withCredentials([
file(credentialsId: 'settings-xml', variable: 'SETTINGS')])
stage('Deploy')
gitlabCommitStatus(name: 'Deploy')
// Upload the Snapshot artefact
sh "mvn -s $SETTINGS clean verify"
Parece que también se puede usar en canalizaciones declarativas, pero no lo probé yo mismo.
Conseguir que una canalización de Jenkins use contenedores de Docker para los Agentes de Jenkins, y que las compilaciones compartan un repositorio local de Maven, es complicado porque hay dos problemas que resolver: compartir los archivos del repositorio local y garantizar que los archivos tengan permisos utilizables.
Creé un Docker Volume para contener los archivos compartidos:
docker volume create maven-cache
Luego le dijo a Jenkins que montara ese Volumen Docker en una ubicación adecuada para cada Agente, haciendo que le diera un --mount
opción a su docker run
mando. Eso hace que el volumen de Docker esté disponible … pero propiedad de root
, en lugar del jenkins
usuario que ejecuta el Agente.
Una complicación para solucionar ese problema de permisos es que Jenkins docker run
su imagen usando el UID de Jenkins, y no puede saber cuál será ese UID. Como he señalado en otra parte, puede solucionarlo utilizando algunos comandos de ejecución mágica de script de shell y para configurar el jenkins
nombre de usuario (y docker
nombre de grupo, si es necesario) para su imagen de Agente.
Puede solucionar el problema de permisos agregando sudo
a su imagen de Docker, y configurar la imagen para permitir el jenkins
usuario para ejecutar sudo
comandos sin contraseña. Entonces, un paso inicial de la canalización de Jenkins puede usar sudo
para crear un directorio adecuado para contener el repositorio local, dentro del montaje compartido, y cambiar el propietario de ese directorio para que sea jenkins
.
Finalmente, puede configurar un archivo de configuración de Maven para que lo use el Agente de Jenkins, que le dice a Maven que use el repositorio local compartido.
Mi Jenkinsfile
es así:
pipeline {
agent
dockerfile
filename 'Dockerfile.jenkinsAgent'
additionalBuildArgs '--build-arg JENKINSUID=`id -u jenkins` --build-arg JENKINSGID=`id -g jenkins` --build-arg DOCKERGID=`stat -c %g /var/run/docker.sock`'
args '-v /var/run/docker.sock:/var/run/docker.sock --mount type=volume,source=maven-cache,destination=/var/cache/maven -u jenkins:docker'
stages {
...
stage('Prepare')
steps
sh '[ -d /var/cache/maven/jenkins ]
Y los pasos posteriores con Maven también dicen mvn -B -s maven-jenkins-settings.xml ...
.
Mi Dockerfile.jenkinsAgent
es así:
FROM debian:stretch-backports
ARG JENKINSUID
ARG JENKINSGID
ARG DOCKERGID
# Add Docker CE
RUN apt-get -y update &&
apt-get -y install
apt-transport-https
ca-certificates
curl
gnupg
lsb-release
software-properties-common
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
RUN add-apt-repository
"deb [arch=amd64] https://download.docker.com/linux/debian
$(lsb_release -cs)
stable"
RUN apt-get -y update &&
apt-get -y install
docker-ce
docker-ce-cli
containerd.io
# Add the build and test tools and libraries
RUN apt-get -y install
...
maven
sudo
...
# Set up the named users and groups
# Installing docker-ce will already have added a "docker" group,
# but perhaps with the wrong ID.
RUN groupadd -g $JENKINSGID jenkins
RUN groupmod -g $DOCKERGID docker
RUN useradd -c "Jenkins user" -g $JENKINSGID -G $DOCKERGID -M -N -u $JENKINSUID jenkins
# Allow the build agent to run root commands if it *really* wants to:
RUN echo "jenkins ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers
(Si su canalización de Jenkins no ejecuta los comandos de Docker, podría eliminar los comandos RUN para instalar Docker, pero luego tendría que groupadd
el docker
grupo, en lugar de groupmod
)
Y el archivo de configuración de Maven para el agente de Jenkins (maven-jenkins-settings.xml
) es así:
/var/cache/maven/jenkins
false
Si sostienes alguna perplejidad o forma de refinar nuestro crónica puedes añadir una nota y con gusto lo ojearemos.