Docker和Jenkins像DevOps界的巧克力和花生酱那样,它们的组合产生了无数的机会,当然也产生了很多难题,笔者将提及这两个方面。
本文中,我假定读者已经熟悉Jenkins和Docker,我将把焦点放在特定的配置上而不是把笔墨花费在许多博文已经介绍过的入门概念上。
设定目标
我所要达成的目标其实非常简单:在一个容器中搭建Jenkins主节点,并且在多个主机上搭建多个JNLP代理容器。这些代理节点可以运行在不同的AWS VPC或者ECS上。
我的目标是得到一个能在任何主机上部署的通用配置,而每个项目分别定义各自的构建环境。这样各个开发团队就可以掌控这份配置,而不用经由Jenkins的构建团队。我会尽量避免构建一个特定工具集的代理节点。容器技术能实现这样的构建环境,但是要真正把每个细节都做好绝对是一个挑战。
为了实现这个目标,我还使用了Jenkins Pipeline / Workflow插件。这个插件让你能非常优雅地使用DSL语言描述构建过程,例如这样简单地定义:
node('test-agent') {
stage "Container Prep"
// do the thing in the container
docker.image('maven:3.3.3-jdk-8').inside {
// get the codez
stage 'Checkout'
git url: 'https://github.com/damnhandy/Handy-URI-Templates.git'
stage 'Build'
// Do the build
sh "./mvnw clean install"
}
}
这个pipeline会在一个名为”test-agent”的Jenkins代理上执行,它会基于“maven”3.3.3-jdk-8”镜像构建一个容器。这个pipeline在物理节点上能正常运行,但是在容器中运行则会报错。
运行在Docker中的Docker
在容器中运行Jenkins的主或从节点,可能有人会以为我需要特权模式来使用”Docker in Docker”,但是我并没有,Jérôme Petazzoni发表了一篇文章《用Docker-in-Docker来构建持续集成环境?请三思》,你应该参考一下这篇文章。
如果你还在使用wrapdocker的脚本,你应该