图中,我们专门设计了一个环节用于生成唯一发布包,它打包所有War/Jar、数据库迁移脚本以及配置信息。因此,无论是手工部署还是利用Docker容器自动化部署,我们都使用相同的发布包,这样做也满足持续交付的单一制品原则(Single Source Of Truth,Single Artifact)。
一、创建Jenkins容器
相比于直接把Jenkins安装到主机上,我们选择把它做为Docker容器单独使用,这样就省去了每次安装Jenkins本身及其依赖的过程,真正做到了拿来就可以使用。
Jenkins容器使创建一个全新的CI变的非常简单,只需一行命令就可完成:
docker run -d -p 9090:8080 ——name jenkins jenkins:1.576
该命令启动Jenkins容器并将容器内部8080端口重定向到主机9090端口,此时访问:主机IP:9090,就可以得到一个正在运行的Jenkins服务了。
为了降低升级和维护的成本,可将构建Jenkins容器的所有操作写入Dockerfile并用版本工具管理,如若需要升级Jenkins,只要重新build一次Dockerfile:
每次build时标注一个新的tag:“docker build -t jenkins:1.578 —rm .”
另外,建议使用Docker volume功能将外部目录挂载到JENKINS_HOME目录(Jenkins会将安装的插件等文件存放在这个目录),这样保证了升级Jenkins容器后已安装的插件都还存在。例如:将主机/usr/local/jenkins/home目录挂载到容器内部/var/lib/jenkins:
“docker run -d -p 9090:8080 -v /usr/local/jenkins/home:/var/lib/jenkins ——name jenkins jenkins:1.578”
二、使用Docker容器作为Jenkins容器的Slave
在使用Jenkins容器时,我们有一个原则:不要在容器内部存放任何和项目相关的数据。因为运行中的容器不一定是稳定的,而Docker本身也可能有Bug,如果把项目数据存放在容器中,一旦出了问题,就有丢掉所有数据的风险。因此,我们建议Jenkins容器仅负责提供Jenkins服务而不负责构建,而是把构建工作代理给其他Docker容器做。
例如,为了构建Java项目,需要创建一个包含JDK及其构建工具的容器。依然使用Dockerfile构建该容器,以下是示例代码(可根据项目实际需要安装其他工具,比如:Gradle等):
在这里安装openssh-server的原因是Jenkins需要使用ssh的方式访问和操作Slave,因此,ssh应作为每一个Slave必须安装的服务。运行该容器:
“docker run -d -P —name java java:1.7”
其中,-P是让Docker为容器内部的22端口自动分配重定向到主机的端口,这时如果执行命令:“docker ps”,会发现端口22被重定向到了49153端口。这样,Jenkins就可以通过ssh直接操作该容器了(在Jenkins的Manage Nodes中配置该Slave)。
有了包含构建Java项目的Slave容器后,我们依然要遵循容器中不能存放项目相关数据的原则。此时,又需要借助volume:“docker run -d -v /usr/local/jenkins/workspace:/usr/local/jenkins -P —name java java:1.7”。这样,我们在Jenkins Slave中配置的Job、Workspace以及下载的源码都会被放置到主机目录/usr/local/jenkins/workspace下,最终达成了不在容器中放置任何项目数据的目标。
相比直接将Jenkins安装到主机上的方式,Jenkins容器的解决方案带来了明显的好处:
1. 重用更加简单,只需一行命令就可获得CI的服务;
2. 升级和维护也变的容易,只需要重新构建Jenkins容器即可;
3. 灵活配置Slave的能力,并可根据企业内部需要预先定制具有不同能力的Slave,比如:可以创建出具有构建Ruby On Rails能力的Slave,可以创建出具有构建NodeJS能力的Slave。当Jenkisn需要具备某种能力的Slave时,只需要docker run将该容器启动,并配置为Slave,Jenkins就立刻拥有了构建该应用的能力。
如果一个组织内部项目繁多且技术栈复杂,那么采用Jenkins结合Docker的方案会简化很多配置工作,同时也带来了相率的提升。
三、更好的组织自动化脚本
为了更好的组织自动化发布脚本,版本化控制是必须的。我们在项目中单独创建了一个目录:deploy,在这个目录下存放所有与发布相关的文件,包括:用于自动化发布的shell脚本,用于构建镜像的Dockerfile,与环境相关的配置文件等等,其目录结构是:
当需要向某一台机器上安装java和jboss镜像时,只需要运行“bin/install.sh images -p 10.1.2.15 java jboss”。
而在部署的过程中,我们采用了角色化部署的方式,角色化后,使部署变的更为清晰明了,而每个角色单独的deploy脚本更有利于划分责任避免和其他角色的干扰。在roles目录下,它是这样的:
四、构建企业内部Docker registry
Docker Registry是镜像仓库,可以向Registry中提交push镜像同时又可以从中下载pull。
构建本地的Registry非常简单,执行命令:“docker run -p 5000:5000 registry”
更多关于如何使用Registry可以参考地址:https://github.com/docker/docker-registry
当搭建好Registry后,就可以向它push你的镜像了:“docker push your_registry_ip:5000/base:centos”
使用下面的方式下载镜像:
docker pull your_registry_ip:5000/jboss:4.3
http://insights.thoughtworkers.org/start-continuous-delivery-with-docker/
网友评论