笔者是独立翻译实验,不允许转载
Using Docker with Pipeline
许多组织都是用Docker来统一编译和测试环境,提供一个发布应用的有效机制。从Pipeline 2.5版本或者更高,Pipeline内嵌支持同Jenkinsfile内Docker交互。
本章覆盖了使用Jenkinsfile内Docker基本使用,并不包括Docker的使用。关于Docker使用,请参考https://docs.docker.com/get-started/。
Customizing the execution environment
Pipeline较早被设计使用Docker images作为执行环境,执行一个单独的stage或者整个Pipeline,意味着用户可以定义他们的Pipeline需要使用的工具,不必手动配置代理。实践上,任何工具都能被打包到Docker container中,能被一个Jenkinsfile容易使用。
当Pipeline执行的时候,Jenkins自动开启特定的container,执行里面定义的steps。
Caching data for containers
许多编译工具会下载外部依赖,并把它们缓存在本地。因为containers初始化的时候是干净的文件系统,这能导致较小的Pipelines,因此他们并不能充分利用硬盘缓存的优势。
Pipeline支持添加定制化参数,参数能被传入到Docker中,允许用户指定特定的Docker Volumes去挂载,Volumes能被用来缓存代理上的数据。下面的例子将在Pipeline运行的时候,缓存~/.m2,可以避免重复下载依赖。
注意:实测表明
使用本地机器的maven repo,不用再单独下载的技巧,要点在于
(1).启动docker的时候就要传入repo
(2).启动编译命令的时候,要再传一次repo,否则mvn会单独下载依赖的包
Using multiple containers
现在非常普遍,代码依赖多个,不同的技术。例如一个库既有Java-based的后端API实现,也有JavaScript基础的前端实现。组合Docker和Pipeline,允许Jenkinsfile通过agent{}在不同阶段使用多种技术。
Using a Dockerfile
对于那些需要特定执行环境的项目,Pipeline同样支持在Dockerfile中创建和运行容器(container)。同前面使用”off-the-shell”容器相反,使用代理{dockerfile true}语法将创建新的image,而不是从Docker Hub拉取。
重新使用前面的例子,用一个定制化的Dockerfile。
Dockerfile
把这个提交到源代码库的根目录,Jenkinsfile被改变去构建一个基于这个Dockerfile的容器,用这个容器运行定义好的steps。
agent { dockerfile true}语法支持许多其他选项,关于这些选项详见Pipeline Syntax部分。
Using a Dockerfile with Jenkins Pipeline
注意:笔者添加。
其他一些使用说明,请参见:https://github.com/jenkinsci/pipeline-model-definition-plugin/wiki/Syntax-Reference
其实本例的目的:仅仅只是制作了一个新的docker image,完全可以自己手动做,也可以使用linux shell脚本和docker配合使用做出来,不一定非要通过Jenkins的插件做。此方法的一个不好的地方就是:自己设置生成的image的名字以后,通过参数加进去,最终会出来两个一样的docker image,因为再生成的时候,必须要设置一个名字,哪怕是随机的名字。
参数如下:1
2
3
4
5
6agent { dockerfile true }
agent {
dockerfile {
additionalBuildArgs '-t node-svn:7-alpine'
}
}
Specifying a Docker label
默认情况下,Pipeline假设任何配置的代理都能运行基于Docker的Pipeline。对于Jenkins环境,有macOS,Windows或者其他不能运行Docker代理,默认设置可能有问题。Pipeline在Manage Jenkins页面(manage Jenkins–>Configuration)上提供一个全局选项。
注意:测试表明
此label只是为了区分在哪个node上运行,本例运行的node label为:linux,其实换成master应该也可以,如果不设置,就会寻找一个默认的本地的符合条件的node执行。
Advanced Usage with Scripted Pipeline
Running “sidecar” containers
在Pipeline中使用Docker是运行服务/一套测试的一个有效方式,类似于sidecar模式,Docker Pipeline能在后台运行容器。使用sidecar方法,对于每一次Pipeline运行,Pipeline能有一个干净的容器。
考虑一个依赖于本地MySQL数据库的集成测试套件。使用插件docker-workflow插件实现的withRun方法,一个能运行MySQL作为sidecar的Jenkinsfile文件:
注意:本例笔者运行失败。
(1).本地必需安装有mysqladmin工具,否则执行失败。
(2).docker run -d -e MYSQL_ROOT_PASSWORD=my-secret-pw -p 3306:3306 mysql:5这样启动以后,确实发现container里面的mysql启动成功,但是如果使用docker run -d -e MYSQL_ROOT_PASSWORD=my-secret-pw -p 3306:3306 mysql:5 /bin/sh进去以后,发现mysql没有启动,或者说启动失败。
示例可以更进一步,同时使用两个容器。一个”sidecar”运行MySQL,另一个用Docker container links提供执行环境。
上面的示例使用withRun暴露的对象,withRun有运行的容器ID。用容器ID,Pipeline能创建一个链接,通过传递客制化的Docker参数到inside()方法。
Id属性对于查看正在运行容器的log同样有用:
注意:笔者实测,
执行的sh命令都是在container里面执行的。所以起了两个container。
Building containers
创建一个Docker image,插件docker-workflow同样提供一个build()方法创建新的image,在Pipeline运行的时候,从代码库中的Dockerfile文件也能创建image。
使用docker.build(“my-image-name”))语法的一个主要好处:脚本是的Pipeline能使用返回值用于后面的Docker Pipeline调用,例如:
返回值能被用来保存Docker image到Docker Hub或者私有的Registry,通过push()方法,例如:
Image的tag属性常用方法是latest标记。push()方法接受一个可选的tag参数,允许Pipeline用不同的标记存储customImage,例如:
笔者注:
此类制作image,完全可以shell和docker独立做,如有必要,可以来此参照执行。
Using a remote Docker server
默认情况下,插件docker-workflow会和本地的Docker交互,典型的是通过/var/run/docker.sock。
选择一个不是非默认Docker server,例如Docker Swarm,withServer()方法可以使用。
通过传递一个URI,可选的Docker Server Certificate Authentication认证信息,方法如下:
注意:inside()和build()将不能同Docker Swarm server正常工作。
对于函数inside()正常执行,Docker server和Jenkins代理必须使用同样的文件系统,以便工作空间能被挂载。
现在Jenkins插件和Docker CLI都不能自动检测远端server运行的case;一个典型的现象就是嵌套sh命令出现错误,例如
当Jenkins检测到代理运行在Docker容器中的时候,它将自动传递–volumes-from参数到inside容器,确保它能同代理共享工作空间。
另外,一些Docker Swarm版本并不支持定制化的Registry。
Using a custom registry
默认情况下,docker-workflow插件使用默认的Docker Registry—Docker Hub。
为了使用定制化的Docker Registry,脚本是的Pipeline用户可以用withRegistry方法去包含steps,传递定制化的Registry URL,例如:
对于需要认证的Docker Registry,从Jenkins主页上添加用户名/密码项,并使用认证ID作为withRegistry()的第二个参数。
注意:此类是制作docker image然后保存到私有的registry,可以shell和docker实现,如有必要,来此参照制作。