Docker和Jenkins像DevOps界的巧克力和花生醬那樣,它們的組合產生了無數的機會,固然也產生了不少難題,筆者將說起這兩個方面。node
本文中,我假定讀者已經熟悉Jenkins和Docker,我將把焦點放在特定的配置上而不是把筆墨花費在許多博文已經介紹過的入門概念上。git
設定目標github
我所要達成的目標其實很是簡單:在一個容器中搭建Jenkins主節點,而且在多個主機上搭建多個JNLP代理容器。這些代理節點能夠運行在不一樣的AWS VPC或者ECS上。docker
個人目標是獲得一個能在任何主機上部署的通用配置,而每一個項目分別定義各自的構建環境。這樣各個開發團隊就能夠掌控這份配置,而不用經由Jenkins的構建團隊。我會盡可能避免構建一個特定工具集的代理節點。容器技術能實現這樣的構建環境,可是要真正把每一個細節都作好絕對是一個挑戰。安全
爲了實現這個目標,我還使用了Jenkins Pipeline / Workflow插件。這個插件讓你能很是優雅地使用DSL語言描述構建過程,例如這樣簡單地定義:架構
```js
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"
}
}
```socket
這個pipeline會在一個名爲"test-agent"的Jenkins代理上執行,它會基於「maven」3.3.3-jdk-8」鏡像構建一個容器。這個pipeline在物理節點上能正常運行,可是在容器中運行則會報錯。maven
運行在Docker中的Dockeride
在容器中運行Jenkins的主或從節點,可能有人會覺得我須要特權模式來使用"Docker in Docker",可是我並無,Jérôme Petazzoni發表了一篇文章[《用Docker-in-Docker來構建持續集成環境?請三思》](https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/),你應該參考一下這篇文章。工具
若是你還在使用wrapdocker的腳本,你應該問問本身爲何,由於這樣用起來更簡單:
```sh
docker run -v ${JENKINS_HOME}:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 8080:8080 -p 50000:50000 \
index.csphere.cn/microimages/jenkins
```
這個命令會啓動Jenkins而且能夠擁有全部的容器操做功能,因此並不須要特權模式來啓動容器,也不須要"Docker-in-Docker"模式。
有個地方須要注意:在這裏你不能用官方的Jenkins鏡像,由於jenkins用戶須要屬於docker用戶組,這樣才能使用socket,從而能在容器中的Jenkins調用docker,最終實現經過Jenkins構建和運行其餘容器。
Jenkins JNLP代理容器
在「系統管理」=>「管理節點」頁面,點擊「新建節點」,能夠添加slave:
Jenkins從節點的啓動方式與主節點相似,它也須要鏈接docker的socket接口,你能夠這樣啓動:
```sh
docker run -v ${JENKINS_HOME}:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
--name=jenkins-slave \
-d index.csphere.cn/microimages/jenkins-slave \
-url http://jenkins-master:8080/ \
a0a1b92971030d5f5dd69bd972c6cd899f705ddd3699ca3c5e92f937d860be7e \
test-agent
```
與Jenkins主節點同樣,你須要確保jenkins用戶有權限訪問docker socket接口,我使用的是Jenkins jnlp從節點容器,這樣,這個slave容器就能夠執行構建操做了,注意secret參數須要從master上的某個slave裏查看。
準備就緒,開始構建
在容器中開始一個構建過程不難,問題是你必需讓這個代理容器綁定一個宿主機上的路徑<code>${JENKINS_HOME}:/var/jenkins_home</code>,並且被構建的容器也須要這個目錄的訪問權限。
```sh
docker run -t -d -u 1000:1000 -w /var/jenkins_home/workspace/uri-templates-in-docker \
-v /var/jenkins_home/workspace/uri-templates-in-docker:/var/jenkins_home/workspace/uri-templates-in-docker:rw \
-e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** \
-e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** \
maven:3.3.3-jdk-8 cat
```
這個容器會把宿主機上的 /var/jenkins_home/workspace/uri-templates-in-docker目錄掛載到容器化環境以供Maven使用,而且會把這個路徑設置成當前工做路徑,這些在物理機上都能正常運行,可是要在容器中執行,我須要嘗試這樣作:
這樣明顯不行,由於我把docker socket端口映射到了Jenkins代理容器上,掛載到Jenkins agent容器的全部卷實際上都是引用宿主上的路徑,假定宿主上的<code>${JENKINS_HOME}</code>是<code> /opt/jenkins_home</code>,如下的命令應該生效:
```sh
docker run -t -d -u 1000:1000 -w /opt/jenkins_home/workspace/uri-templates-in-docker \
-v /opt/jenkins_home:/var/jenkins_home/workspace/uri-templates-in-docker:rw \
-e ********
maven:3.3.3-jdk-8 cat
```
總結
把構建環境容器化是一個很是好的主意,這樣節省了不少時間。
注意,這份代碼可能不正正知足你的需求,可是起碼是一個demo,我但願本文能幫助更多人用上Jenkins的容器來構建應用。
關於希雲cSphere
希雲cSphere是一個高度集成、功能強大的Docker私有云平臺和類PaaS解決方案,其架構設計借鑑了VMWare vSphere的思想。系統健壯性比肩VMWare這樣的商業產品,產品通過一年多十多個版本的迭代更新,在內部更是經歷了1000次以上的破壞性測試,目前已經在金融、製造、遊戲、安全、電商、教育等多個領域落地。
cSphere的亮點:
- 平臺適應應用,不須要應用適應平臺。
- 多應用架構多場景支持,希雲承諾不管是5年前的應用、如今的甚至5年後的應用架構均可以在希雲上完美支持
- 搬遷現有業務,代碼、架構無需任何修改
- 希雲產品以自研發爲主,拋棄了「拼湊」模式,有力保證了工程質量
- 真正企業級的PaaS,可知足高複雜項目需求
歡迎聯繫咱們:
- 電話 400-686-1560
- 郵箱 docker@csphere.cn