Jenkins是基于Java开发的一个开源软件项目。Jenkins允许持续集成工具和持续交付项目,可以处理任何类型的构建或持续集成,例如我们可以使用Jenkins来对Maven开发的项目进行打包、部署等。
1 环境准备
准备一台安装了Docker、Docker-Compose、JDK、Maven环境的Linux主机。本文使用的软件环境为:
- 操作系统:Ubuntu 16.04.4 LTS
- Docker:1.12.3, build 6b644ec
- Docker-Compose:1.9.0-rc4, build 181a4e9
- JDK:jdk1.8.0_151
- Maven:apache-maven-3.3.9
- Jenkins Docker image:jenkinsci/blueocean:latest
2 搭建私有的Docker镜像仓库
首先,我们需要搭建一个私有的Docker镜像仓库(Docker Private Registry)来存放我们制作的Docker镜像。我们使用Jenkins将项目打包成Docker镜像后,会推送到我们的私有仓库里面。私有仓库的搭建教程在这里:【搭建一个私有的Docker镜像仓库】
3 安装&配置Jenkins
我们通过Jenkins的Docker镜像来安装Jenkins,拉取Jenkins的docker镜像到本地主机:1
docker pull jenkinsci/blueocean
编辑docker-compose.yml
文件,添加以下内容:1
2
3
4
5
6
7
8
9
10
11
12
13
14version: '2'
services:
jenkins:
image: jenkinsci/blueocean:latest
container_name: jenkins
ports:
- '8080:8080'
- '50000:50000'
volumes:
- '/docker/volumes/jenkins:/var/jenkins_home'
- '/var/run/docker.sock:/var/run/docker.sock'
- '/usr/local/jdk1.8.0_171:/usr/local/jdk1.8.0_171'
- '/usr/local/apache-maven-3.3.9:/usr/local/apache-maven-3.3.9'
restart: always
使用docker-compose
指令启动Jenkins容器并查看Jenkins的启动日志:1
docker-compose up -d jenkins && docker logs -f jenkins
注意:查看Jenkins启动日志,Jenkins启动过程有可能会遇到错误:
touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
报错原因:Jenkins容器里面没有外部主机/docker/volumes/jenkins
目录的访问权限。
解决方案:执行sudo chown -R 1000:1000 /docker/volumes/jenkins
指令,将/docker/volumes/jenkins
目录及其子目录的用户以及用户组设置成Jenkins的用户。
成功启动Jenkins后,访问主机的8080端口(例如http://localhost:8080
),来到Jenkins的初始化页面:【解锁Jenkins(Unlock Jenkins)】
页面提示输入管理员(admin
)的初始化密码,密码存放在/var/jenkins_home/secrets/initialAdminPassword
文件中,由于/var/jenkins_home
是Jenkins容器中的目录并且我们已经通过数据卷映射到了外部主机的/docker/volumes/jenkins
目录。所以我们可以直接使用以下指令来查看初始密码:1
2cat /docker/volumes/jenkins/secrets/initialAdminPassword
3677559e7c8244d1aa296b3bdf0c8685
3677559e7c8244d1aa296b3bdf0c8685
即为初始密码。输入密码后,来到安装插件的页面,选择【安装推荐的插件(Install suggested plugins)】即可:
插件安装完毕后,Jenkins会提示创建一个新的管理员账号。这里可以创建一个新账号也可以继续使用初始化的账号admin
。账号创建完毕后,进入Jenkins URL配置页面,点击【保存并完成(Save and Finish)】,就可以开始使用Jenkins:
4 配置Git、JDK、Maven
登录Jenkins,依次进入【系统管理 -> 插件管理 -> 可选插件】,搜索并安装以下插件:
1. SSH
插件——用于SSH登录远程主机拉取代码或者部署服务;
2. Publish Over SSH
插件——用于将项目部署到远程机器上(SSH登录然后执行部署脚本);
3. Maven Integration
插件——用于创建一个Maven的构建项目;
4. CloudBees Docker Build and Publish
插件——用于将项目打包成Docker镜像并push到我们搭建的私有镜像仓库中。
进入【系统管理 -> 全局工具配置】:
配置Git:找到Git
选项;因为jenkinsci/blueocean
镜像已经自带了Git,所以无需我们安装Git。
配置JDK:找到JDK
选项;配置JDK安装路径为我们docker-compose.yml
文件中映射的容器内部的目录/usr/local/jdk1.8.0_171
。
配置Maven:找到Maven
选项;配置Maven的安装路径为我们docker-compose.yml
文件中映射的容器内部的目录/usr/local/apache-maven-3.3.9
。
5 构建一个Maven项目并打包成Docker镜像
现在我们来新建一个Jenkins的Maven项目任务:
在项目的配置页面,拉到【源码管理】配置项,配置Jenkins从哪个地方拉取代码:
上图中,我们填写了一个GitHub源码地址,但是出现错误信息:Failed to connect to repository : Command "git ls-remote -h git@github.com:biteeniu/java-base-example.git HEAD" ...
。这是因为我们的Jenkins还没有配置GitHub仓库源码的访问认证信息,所以没有权限拉取代码。我们点击上图中红色框框来添加认证信息:在添加认证信息之前,先使用ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
生成SSH公钥文件(id_rsa.pub
)和私钥文件(id_rsa
)。将公钥文件的内容上传到GitHub账号中,将私钥文件内容粘贴到Jenkins的认证信息添加页面:
认证信息添加完后,重新在【源码管理】中,选择刚刚添加的认证信息,如果认证信息没问题,红色字体的错误信息就会消失:
拉到【Build】配置项,配置Maven打包指令,比如clean package -Dmaven.test.skip=true
或clean assembly:assembly
(根据项目使用的Maven Build插件来定):
拉到【Post Steps】配置项,配置打包后的操作。这里希望Maven将项目打包成JAR包后,执行Docker Build and Publish
,即打包成Docker镜像并push到我们的私有仓库:
1. Repository Name
是我们打包的Docker镜像的名称,可自己定义;
2. Tag
是我们打包的Docker镜像的TAG,可自己定义;也可以使用Jenkins变量,比如${BUILD_NUMBER}
;
3. Docker Host URI
是Jenkins使用的Docker服务的地址,这里我们的Jenkins使用本机的Docker服务,所以可以不填写,使用默认的。
4. Docker registry URL
是我们搭建的Docker私有镜像仓库的地址;
5. Registry credentials
是我们搭建的Docker私有仓库的访问认证,这里我搭建仓库的时候设置了用户名/密码认证。若搭建仓库的时候没有设置认证,则不需要填写这里。
以上基本配置完毕,我们点击【保存】,然后执行构建。
构建过程中,在执行打包Docker镜像的时候,可能会出现以下错误:
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.35/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&pull=1&rm=1&session=b6fdf5eb05a09a5bbfaeb901039eeaef7839ee0c5a20176cc66fe1629894d763&shmsize=0&t=10.200.0.206%3A5000%2Fsenthink-register-center%3A1.0.0&target=&ulimits=null: dial unix /var/run/docker.sock: connect: permission denied
这是由于Jenkins容器内部没有权限访问宿主机的Docker服务,没有权限连接宿主机的/var/run/docker.sock
;我们需要在启动Jenkins容器的时候加上group_add
选项。
先在宿主机上运行指令stat -c %g /var/run/docker.sock
来查看/var/run/docker.sock
文件所属的用户组ID:1
2stat -c %g /var/run/docker.sock
995
所以,编辑docker-compose.yml
文件,添加group_add
选项:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16version: '2'
services:
jenkins:
image: jenkinsci/blueocean:latest
container_name: jenkins
group_add:
- 995
ports:
- '8080:8080'
- '50000:50000'
volumes:
- '/docker/volumes/jenkins:/var/jenkins_home'
- '/var/run/docker.sock:/var/run/docker.sock'
- '/usr/local/jdk1.8.0_171:/usr/local/jdk1.8.0_171'
- '/usr/local/apache-maven-3.3.9:/usr/local/apache-maven-3.3.9'
restart: always
最后,执行docker-compose stop jenkins && docker-compose rm -f jenkins && docker-compose up -d jenkins
指令来停止、删除和启动Jenkins容器。点击重新构建项目,即可成功构建、打包。如果构建成功,则Jenkins已经将项目打包成Docker镜像,并将Docker镜像push到了我们的私有镜像仓库(10.200.0.206:5000
)中。
6 远程部署项目
我们已经成功将项目构建、打包成了一个Docker镜像,并推送到了私有的镜像仓库10.200.0.206:5000
中。接下来我们通过Jenkins配置后续的部署操作:进入【系统管理 -> 系统设置】,配置一个【SSH remote hosts】远程主机,我们需要让Jenkins通过SSH登录到此主机上执行一些指令来部署我们的项目。
回到我们项目的配置,找到【Post Steps】选项,增加一个Execute shell script on remote host using ssh
操作,在SSH site
选项中下拉选择我们刚刚添加的【SSH remote hosts】远程主机:
注意:在构建项目之前,我们需要事先登录我们的远程主机,编辑好服务部署的docker-compose.yml
文件:1
2
3
4
5version: '2'
services:
rabbitmq-delay-queue:
image: 10.200.0.206:5000/rabbitmq-delay-queue:1.0
container_name: rabbitmq-delay-queue
然后,我们再次点击【构建】,重新构建我们的项目。这时候,当Docker镜像制作完毕并推送到私有仓库后,Jenkins会通过SSH登录我们指定的远程主机,执行部署指令!
以上,我们就完成了一次Jenkins + Git + Maven + Docker
的持续集成、部署实践。
——————–【参考文章】——————–