我想在Docker容器中运行我的Maven构建。我不想在每个版本中都上传所有依赖关系,所以我尝试安装Using Docker with Pipeline中记录的主机的本地Maven存储库:
为容器缓存数据
[...]
Pipeline支持添加传递给Docker的自定义参数,允许用户指定要安装的自定义Docker卷,该卷可用于在管道运行之间在代理上缓存数据。下面的示例将利用Maven容器在管道运行之间缓存〜/ .m2,从而避免为管道的后续运行重新下载依赖项。
pipeline { agent { docker { image 'maven:3-alpine' args '-v $HOME/.m2:/root/.m2' } } stages { stage('Build') { steps { sh 'mvn -B' } } } }
代码
pipeline {
agent {
docker {
image 'maven:3-alpine'
args '-v /home/jenkins/.m2:/root/.m2'
}
}
stages {
stage('Build') {
steps {
sh 'mvn -B clean verify'
}
}
}
}
登录
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on jenkins-docker in /home/jenkins/workspace/Test/Docker Test@2
[Pipeline] {
[Pipeline] sh
+ docker inspect -f . maven:3-alpine
.
[Pipeline] withDockerContainer
jenkins-docker does not seem to be running inside a container
$ docker run -t -d -u 1000:1000 -v /home/jenkins/.m2:/root/.m2 -w "/home/jenkins/workspace/Test/Docker Test@2" -v "/home/jenkins/workspace/Test/Docker Test@2:/home/jenkins/workspace/Test/Docker Test@2:rw,z" -v "/home/jenkins/workspace/Test/Docker Test@2@tmp:/home/jenkins/workspace/Test/Docker Test@2@tmp:rw,z" -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** maven:3-alpine cat
[...]
[DEBUG] Reading global settings from /usr/share/maven/conf/settings.xml
[DEBUG] Reading user settings from ?/.m2/settings.xml
[DEBUG] Reading global toolchains from /usr/share/maven/conf/toolchains.xml
[DEBUG] Reading user toolchains from ?/.m2/toolchains.xml
[DEBUG] Using local repository at /home/jenkins/workspace/Test/Docker Test@2/?/.m2/repository
[DEBUG] Using manager EnhancedLocalRepositoryManager with priority 10.0 for /home/jenkins/workspace/Test/Docker Test@2/?/.m2/repository
问题
构建~/m2
目录为空后,未添加任何文件/目录。所有文件都添加到/home/jenkins/workspace/Test/Docker Test@2/?/.m2
下( Test 是文件夹的名称, Docker Test 是竖线的名称)。
问题在于,该目录仅用于该特定管道,而不用于其他管道,因此我无法与其他管道/作业共享本地Maven存储库。
我的settings.xml
也未使用,因为它保存在~/m2
下。
是否存在使用Docker与不同管道共享本地Maven存储库和Maven设置的解决方案?
答案 0 :(得分:3)
我找到了一种解决方法,请参见Local settings.xml not picked up by Jenkins agent:
该问题与jenkins用于运行容器的
-u uid:gid
有关。您可能知道正在运行的映像仅创建了一个用户root
,因此当詹金斯传递其自己的uid和gid时,该用户将没有条目,因此也不会为此声明$HOME
。 / p>如果只希望独立于用户运行构建,则可以将以下内容用作代理:
agent { docker { image 'maven:3-alpine' args '-v $HOME/.m2:/root/.m2:z -u root' reuseNode true } }
一些注意事项:
- 如果您注意到我正在使用标志
z
使用的卷,因为我将使用root进行构建,则需要告诉docker该卷将在另一个容器之间共享,然后防止拒绝访问我的jenkins容器(使用用户jenkins而非root运行)- 我告诉jenkins重用Node,因此使用同一映像的任何其他阶段都将在同一容器上执行(这只是为了加快配置时间)
登录
[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
很遗憾,本地存储库/home/jenkins/.m2
中的文件现在由用户root
而非用户jenkins
拥有。那可能导致其他问题。
答案 1 :(得分:0)
获取Jenkins管道以将Docker容器用于Jenkins Agents,以及用于共享Maven本地存储库的构建,因为要解决两个问题,因此很棘手:共享本地存储库文件,并确保文件具有可用权限
我创建了一个Docker Volume来保存共享文件:
docker volume create maven-cache
然后告诉Jenkins通过让其--mount
命令使用docker run
选项,将Docker Volume安装在每个Agent的适当位置。这使Docker卷可用...但是由root
拥有,而不是由运行代理的jenkins
用户拥有。
解决该权限问题的一个复杂方法是,詹金斯将使用Jenkins UID docker run
来映像您的图像,而您不知道该UID是什么。与I've noted elsewhere一样,您可以使用一些shell脚本魔术和RUN命令来解决此问题,以为您的代理程序映像设置jenkins
用户名(和docker
组名)。 / p>
您可以通过以下方法解决权限问题:将sudo
添加到您的Docker映像中,并配置该映像以允许jenkins
用户运行sudo
命令而无需输入密码。然后,早期的Jenkins流水线步骤可以使用sudo
创建一个合适的目录,以在共享安装中保存本地存储库,并将该目录的所有者更改为jenkins
。
最后,您可以设置一个供Jenkins Agent使用的Maven设置文件,它告诉Maven使用共享的本地存储库。
我的Jenkinsfile
是这样的:
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 ] || sudo -n mkdir /var/cache/maven/jenkins'
sh 'sudo -n chown jenkins /var/cache/maven/jenkins'
...
sh 'mvn -B -s maven-jenkins-settings.xml clean'
}
}
随后使用Maven的步骤也说mvn -B -s maven-jenkins-settings.xml ...
。
我的Dockerfile.jenkinsAgent
是这样的:
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
(如果您的Jenkins管道本身不运行Docker命令,则可以删除用于安装Docker的RUN命令,但随后您必须groupadd
docker
组,而不是groupmod
)
Jenkins代理(maven-jenkins-settings.xml
)的Maven设置文件如下:
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>/var/cache/maven/jenkins</localRepository>
<interactiveMode>false</interactiveMode>
</settings>
答案 2 :(得分:0)
Maven需要用户主页才能将工件下载到 在图像中不存在,需要额外的
user.home
Java属性 被设置。
即-Duser.home=/path/to/home/
通过此链接:https://github.com/carlossg/docker-maven#running-as-non-root-not-supported-on-windows
我在声明性Jenkins管道中通过以下配置解决了Jenkins CI上共享Maven缓存的问题。
agent {
docker {
image 'amazoncorretto:8'
label 'docker'
args '-v $HOME/tools:$HOME/tools \
-v $HOME/.m2/:$HOME/.m2 \
-v /etc/passwd:/etc/passwd:ro \
-e MAVEN_CONFIG=$HOME/.m2 \
'
}
}