> 文章列表 > Docker部署的Jenkins集成GitLib/Maven/Java等问题

Docker部署的Jenkins集成GitLib/Maven/Java等问题

Docker部署的Jenkins集成GitLib/Maven/Java等问题

一直认为使用docker来部署一些组件是很方便,不但能一键部署,还能做到资源隔离。但也正是因为“资源隔离”,也埋藏了很多暗坑。本文介绍使用Docker部署Jenkins后,集成其他组件时遇到的一些问题,以及相应的解决方案

Docker部署Jenkins

部署流程可以参见我的这篇文章《docker部署Jenkins》。如果你的Jenkins直接部署在虚机或物理机上,可以绕过这篇文章。

集成GitLab

裸机部署时,我们既可以在“全局配置”中配置gitlab https地址以及API token信息,也可以在project中设置独立的gitlab,都没有问题。

但当Jenkins运行在容器中后,好像都发生了变化。

全局配置集成GitLab

配置方法可以参照其他文档,本文重点讨论出现的问题。

问题:jenkinsClient error: HTTP 302 Found

在“全局配置”中正确配置了gitlab的https地址和API tokens,结果却报错“ HTTP 302 Found”,类似于下图:

 

解决方案

在网上也有相应的解决方案:把https中的域名修改为实际的ip地址即可。我使用的jihulab.com,找个地方ping一下,拿到ip地址,粘贴上去就正常了。

但这中解决方案似乎并不完美。对于像jihulab.com这种大型代码仓库,万一某一天域名对应的ip发生变化了,你就得重新配置一次。

当然,如果是本地测试环境,可以采用此方案。

说明:

目前还没有深究其原因,如果哪位小伙伴知道根本原因的,还请评论区留言

在项目中集成GitLab

即在Jenkins项目中的“源码管理”模块,填写gitlab信息,如下图:

填写好仓库的URL后,会Jenkins会立即测试这个地址。但在容器中的Jenkins会给我们报出各种错误,意思就是连接不上。

问题:认证不通过

这种时候我们第一时间想到的肯定是认证体系没有跟上,于是乎想到了配置“ssh认证”。

来到GitLab中配置:

 在“编辑个人资料”->“SSH秘钥”中,输入你启动jenkins用户根目录下的公钥信息。例如你使用的root用户启动,那么就可以把/root/.ssh/id_pub.rsa中的内容粘贴到GitLab(上图)中的“密钥”框内。如果没有这个文件,可以到用户根目录下执行如下命令:

ssh-keygen

正常(裸机上)情况下,这时候我们就可以访问在gitlab中的项目了。但是在容器中部署的Jenkins就不行!还是会报类似“没有权限”的错误!

什么原因呢?答案就在docker的“资源隔离”的特性。在容器中使用的root用户 和宿主机上的root的用户不是一回事

解决方案

知道了原因,就有了解决方案:

  1. 在进入Jenkins所在的Docker中,生成/root/.ssh/id_pub.rsa文件,将其内容拷贝到GitLab(上图)中的“密钥”框内
  2. 将容器中的/root/.ssh目录映射到宿主机的/root/.ssh,在宿主机/root下执行ssh-keygen
  3. 自行制作Jenkins-Docker镜像,默认生成/root/.ssh/id_pub.rsa文件,以及包含了Jenkins依赖的其他工具、环境变量等。

方案1,缺点很明显:当容器重新run的时候,你还需要再生成一次/root/.ssh/id_pub.rsa,然后粘贴到GitLab中的“密钥”框内。

方案2和方案3,看上去都不错,方案2相对来说更简洁。

我在实践中采用了方案2,按如下指令启动docker,大家可以参考:

docker run -u root -d --name jenkins_01 -p 9988:8080 -p 50000:50000 -v /home/jenkins_home:/var/jenkins_home  -v /root:/root jenkins/jenkins

其中,-v /root:/root 即为关键映射,这样启动后,docker中的Jenkins在连接GitLab时会复用宿主机上的/root/.ssh/id_pub.rsa文件进行认证,即可正常拉取GitLab仓库中的代码。

集成Maven和Java

问题:找不到命令

默认情况下在宿主上可以mvn编译、java -jar启动,但到了docker中却报错:“找不到mvn指令”、“找不到java命令”、“java版本不对”等等问题。

同样的道理,我们要时刻谨记:docker中是一个独立的环境,与宿主机是“资源隔离”的。

解决方案

遇到这种类似的问题,可以采用下面的通用方案:

  • 目录映射

在docker启动时,通过-v参数进行路径映射,让docker共享宿主机的资源。

假设在docker中没有mvn指令,这时候就可以将docker中的某个路径映射到宿主机的MAVEN_HOME:如将宿主机上的/home/maven(里面存放了mvn完整的环境,包括bin、lib以及setting.xml里配置的私有maven仓库路径),映射到容器中的/var/maven上(镜像中要有这个路径,最好是空目录)。

然后在Jenkins的环境变量中配置上maven(可参考另一篇文章《Jenkins代理模式配置Maven工程》)。

这里要重点注意:配置的路径一定是容器中的maven路径,即/var/maven。切记!

  • 重做镜像

这种方式简单、暴力,直接将所需的资源直接写入docker镜像中,但缺乏灵活性。当我们还需要其他工具、而恰巧镜像中没有时,可能就需要重新制作镜像了。

  • 从节点执行任务

可以将这类任务绑定到具备环境的从节点执行。还是以mvn编译为例,可以将任务分派给具备mvn环境的宿主机上执行,也可以解决这个问题。

那么问题来了,我只有1个节点怎么办?

这种情况下除了前面提到的2个方案外,还有一个野路子:把docker中的Jenkins作为主节点,把宿主机作为从节点。如果你的主机资源够用确实可以考虑这个方案,有一点好处是可以模拟出Jenkins的主从协作的模式,显得逼格高一些。


写在最后

像java、npm等工具也一样,如果你采用了docker来部署Jenkins,那么你在Jenkins中调用这些工具是都会存在类似的问题。这时就可以参考本文中提到的几种方案。