Jenkins 管道中的 Docker 代理卷挂载未按预期工作

Posted

技术标签:

【中文标题】Jenkins 管道中的 Docker 代理卷挂载未按预期工作【英文标题】:Docker agent volume mount in Jenkins pipeline not working as expected 【发布时间】:2020-01-03 07:24:56 【问题描述】:

使用卷挂载的 sn-p 会在 $JENKINS_HOME/workspace/<project-name>/?(问号)而不是 $HOME/.m2/ 下创建 maven 依赖项

请注意,settings.xml 镜像到我们的内部存储库。并且关于如何挂载的说明直接取自 jenkins.io

有人知道为什么会这样吗?

pipeline 
    agent 
        docker 
            image 'maven:3-alpine'
            args '-v /tmp/jenkins/.m2:/root/.m2:rw,z'
        
    
    stages 
        stage('Build') 
            steps 
                sh 'mvn clean install -s settings.xml'
            
        
    

这并不像独立使用 Docker 那样简单。我在 Jenkins slave 上创建了 /var/jenkins/.m2 目录,构建将在其中运行。确保新目录具有 775 权限(尽管可能不需要)并且还将所有者更改为与“/var/opt/slave/workspace/pipeline_test”的所有者相同(根据以下日志获取此路径)

$ docker login -u dcr-login -p ******** https://   nexus.corp.zenmonics.com:8449
Login Succeeded
[Pipeline] 
[Pipeline] sh
+ docker inspect -f . nexus.corp.zenmonics.com:8449/maven:3-alpine
.
[Pipeline] withDockerContainer
cucj1sb3 does not seem to be running inside a container
$ docker run -t -d -u 1002:1002 -v /tmp/jenkins/.m2:/root/.m2:rw,z -w 
/var/opt/slave/workspace/pipeline_test -v /var/opt/slave/workspace/pipeline_test:/var/opt/slave/workspace/pipeline_test:rw,z -v /var/opt/slave/workspace/pipeline_test@tmp:/var/opt/slave/workspace/pipeline_test@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 ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** nexus.corp.zenmonics.com:8449/maven:3-alpine cat
$ docker top c7282468dbb6952aadbe4bb495757e7047122b179c81516645ba23759b78c366 -eo pid,comm

Docker Hub (https://hub.docker.com/_/maven) 官方 maven 镜像的声明让我感觉卷挂载更新了

要创建预打包的存储库,请使用以下内容创建 pom.xml 您需要的依赖项并在 Dockerfile 中使用它。 /usr/share/maven/ref/settings-docker.xml 是一个设置文件 将本地存储库更改为 /usr/share/maven/ref/repository,但是 您可以使用自己的设置文件,只要它使用 /usr/share/maven/ref/repository 作为本地仓库。

【问题讨论】:

可能在管道运行期间未设置$HOME,导致-v /.m2:/root/.m2,其中docker run 上下文中的/ 设置为jenkins 工作区目录。我会使用命名卷而不是像那样绑定安装目录。 您好 masseyb,我已更新以添加更多详细信息。我们在运行 Docker 的 Jenkins slave 上运行构建。我们在 Jenkins master 上没有 Docker,master 的作用只是克隆存储库并根据其调度算法将其远程到适当的 slave。如果您注意到上面发布的新日志,则以 /var/opt/slaves 开头的其他卷挂载路径位于从属计算机上。 【参考方案1】:

正如 @masseyb 在 cmets 中提到的,Jenkins 将 $HOME 视为当前的构建上下文。

有两种解决方法:

a) 使用 Jenkins 插件设置 Env 变量

您可以在 Jenkins 中使用Envinject Plugin 设置环境变量。

b) 指定绝对路径而不是$HOME/.m2

您可以为.m2指定绝对路径,例如:

pipeline 
    agent 
        docker 
            image 'maven:3-alpine'
            args '-v /home/samir-shail/.m2:/root/.m2'
        
    
    stages 
        stage('Build') 
            steps 
                sh 'mvn -B'
            
        
    

注意:请检查 Jenkins 是否有权访问您的 $HOME/.m2/ 目录。

【讨论】:

更新了原始票,如果有帮助,还可以查看上面为 masseyb 添加的评论。这不是很明显的设置,因此具有挑战性。可能我会尝试使用体积映射而不是 masseyb 建议的绑定映射,但我记得之前做过,但没有奏效。【参考方案2】:

https://jenkins.io/doc/book/pipeline/docker/ 上的文档在卷安装方面具有误导性和浪费时间。

创建 Docker 容器时,它使用用户 1002 和组 1002 创建。用户 1002 无权访问 /root/.m2,只能访问注入到容器中的工作目录。

Dockerfile

FROM maven:3-alpine

COPY --chown=1002:1002 repository/ /usr/share/maven/ref/repository/

RUN chmod -R 775 /usr/share/maven/ref/repository

COPY settings.xml /usr/share/maven/ref/

Settings.xml

<localRepository>/usr/share/maven/ref/repository</localRepository>

Docker 命令

docker build -t <server>:<port>/<image-name>:<image-tag> .
docker push <server>:<port>/<image-name>:<image-tag>
docker volume create maven-repo

Jenkinsfile

pipeline 
    agent('linux2')  
        docker 
            label '<slave-label-here>'
            image '<image-name>:<image-tag>'
            registryUrl 'https://<server>:<port>'
            registryCredentialsId '<jenkins-credentials-for-docker-login>'
            args '-v maven-repo:/usr/share/maven/ref/repository/'
        
    

    parameters 
        booleanParam(name: 'SONAR', defaultValue: false, description: 'Select this option to run SONAR Analysis')
    

    stages 
        stage('Build') 
            steps 
                sh 'mvn clean install -s /usr/share/maven/ref/settings.xml -f pom.xml'
            
        
    

【讨论】:

以上是关于Jenkins 管道中的 Docker 代理卷挂载未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

Docker 中的 Docker 无法挂载卷

使用 Jenkins 中的 Kubernetes 插件未进行卷挂载

来自 AWS ECR 的 Jenkins 管道 Docker 代理

Docker Windows 容器挂载命名管道

jenkins-使用 Pod 构建任务时挂载 NFS 持久卷到工作目录

docker中启用挂载卷,docker中的新文件会不会同步到