大家好,欢迎来到停止重构的频道。
上期介绍了Jenkins的基本用法,本期补充介绍Jenkins使用docker进行软件编译。
如果对docker不太熟悉,可以先翻看往期《docker详解》。
我们按这样的顺序展开讨论:
1、为什么使用docker编译软件
2、环境准备
3、使用docker编译软件
为什么使用docker编译软件
首先讨论为什么使用docker编译软件。
docker编译软件指的是,将软件的编译环境打包成docker镜像,Jenkins编译软件时,自动下载对应的docker镜像,并启动对应容器进行编译。
相比使用Jenkins插件,或者直接在服务器上安装编译环境并通过shell指令编译。
docker编译显得很麻烦,docker编译需要手工搭建并打包成docker镜像,需要docker镜像服务存储这些镜像,需要Jenkins服务器配置docker环境。
如果Jenkins服务运行在docker中则更麻烦。
如果仅仅是mavean、node等环境就能编译完成,且无多版本切换需求。则docker编译是完全没有必要的。
但是如果编译的程序特别复杂,例如云计算引擎、多版本交叉编译等。或者希望Jenkins能大杂烩地编译各种软件。
那么,docker编译软件的方式则是首选。
因为docker环境隔离的特性,可以对每个项目量身定做一个干净的编译环境。干净的编译环境不会出现底层库冲突等问题。
更重要的是,可以将编译环境以docker镜像的方式保存起来。
我们习惯是将项目代码和对应的docker编译镜像保存在同一个Git仓库。也就是同时备份代码和对应的编译环境。
这样就不会出现光有代码,但无法还原编译环境的困境。
环境准备
在使用docker编译之前,需要做一些环境准备,也就是在Jenkins服务器上安装docker。
如果服务器单纯是给Jenkins用的,且Jenkins不是以docker方式安装的,则在服务器上直接安装docker服务即可。
如果像我们一样,喜欢将Git、Jenkins、文档资料都部署在同一台服务器。且喜欢使用docker运行这些服务的话。
则需要在docker运行的Jenkins中,再内嵌安装docker。以防止污染宿主机docker环境。
但是在docker运行的Jenkins中,再内嵌安装docker是特别麻烦的。
Jenkins官方文档提供了另外一种实现方式,在宿主机docker上运行dind(docker in docker)容器作为docker编译的环境。
这样Jenkins容器就可以远程使用这个docker编译环境了,详细官方文档地址放在评论区。
但是,默认情况下,Jenkins官方镜像不支持远程使用docker,需要在Jenkins容器中安装docker client才能远程使用docker。
具体可以按照官方说明,以dockerfile的方式构造符合要求的Jenkins镜像,再使用这个Jenkins镜像运行对应容器,即可远程使用docker。
这里需要特别说明的是,官网提供的dockerfile可能会由于网络原因构造失败,一般需要配置网络代理才能构造成功。
另外,最好去掉官方dockerfile中的Jenkins用户不然,容器将不能使用apt安装其他软件。
如果希望将旧的Jenkins容器,改为这种docker编译的方式,也就是不希望重新配置Jenkins任务的话。
可以将旧的Jenkins容器中的jenkins_home文件夹拷贝出来,替换到新的Jenkins容器中,并重启容器。
这里需要提醒的是,这种方式只能适合新旧容器中的Jenkins版本相近的情况。
所以在用dockerfile构造新Jenkins镜像时,最好以对应版本的Jenkins镜像作为基础镜像。
Jenkins使用docker编译
环境准备完毕后,Jenkins就可以使用docker编译了。
实现docker编译一般分为3个步骤:编译镜像制作-镜像存储-容器编译。
步骤:镜像制作
首先是制作用于编译软件的docker镜像。
可以使用Ubuntu、CentOS等基础镜像启动一个容器,在此容器上安装编译所需要的环境,并且编写启动脚本。
最后将此容器打包成docker镜像即可。
启动脚本是,用于启动此docker镜像对应的容器时,自动执行相关编译命令。
当然,docker镜像的制作是完全开放的。
我们的建议是,代码下载交由Jenkins完成,代码文件以挂载的方式将其引入容器,启动脚本只写编译程序的命令。
例如,默认情况下,Jenkins会将代码下载在此任务的workspace目录下,则容器启动命令如图所示。
容器启动时会将workspace挂载到容器中的/Code目录,启动脚本可直接对代码进行编译。
编译后的程序可以放在/Code目录中,这样Jenkins就可以在workspace目录下获取到编译后的文件。
步骤:镜像存储
制作后的镜像,可以存储在本地。
但是,我们更推荐将镜像存储在镜像服务当中。
当然,如果不打算集中存储这些镜像的话,则甚至不打包成镜像也是可以的。
我们推荐是,采用Git服务集中存储这些编译镜像。将代码和对应的编译镜像保存在同一个仓库。
以Gitlab为例,需要先在Gitlab的文件配置中打开远程访问的设置,且重启服务。不然docker将不能访问Gitlab。
如果Gitlab是http服务,而非https,则需要对编译用的docker服务进行配置修改,添加刚在Gitlab配置中设置的地址。
不然docker会由于不信任http地址而报错。
接下来需要在Jenkins的容器中,使用docker命令登录Gitlab。登录成功后,即可拉取存储在Gitlab的docker镜像。
在Gitlab管理页面中,可以在对应仓库管理页面的Container Registry中,查看docker登录、更新镜像等命令,或者查看已经上传的镜像。
这里值得一提的是,一个Git仓库可以存储多个版本的编译镜像,推荐docker镜像的版本与代码的tag相呼,应这样能方便复原历史版本编译。
步骤:容器编译
在以上准备工作都完成后,Jenkins就可以使用docker镜像进行编译了。
在Jenkins任务中,可以使用Shell指令或者docker插件完成配置。
这里以Shell指令为例,拉取镜像、使用镜像进行编译如图所示。
其中,拉取镜像的指令虽然每次都会执行,但是docker镜像有分层、识别码等机制。
所以在镜像没有变化或者变化不大的情况下,是不会消耗太多时间的。
另外,在使用镜像进行编译的指令中。
我们推荐采用编译完成后自动删除容器的方式,当启动脚本执行完毕后将自动删除编译容器。
推荐将Jenkins任务的workspace目录挂载到编译容器中,这样后续Jenkins步骤也可以在workspace中找到编译完成的文件。
总结
本期主要介绍了Jenkins使用docker编译软件,可能对大多数开发者来说,没什么必要。
但是,对于维护管理多个项目的团队来说,这种方式是更加推荐的。这种方式对于项目维护、项目归档更加友好。
因为仅仅是备份代码,对代码进行版本管理,而不备份编译环境的话,就很容易出现。
光有代码,而由于人员流动、旧版本开源服务停止维护等原因,导致无法还原编译环境的问题。