前言
最近了解了一番持續(xù)集成丹诀、持續(xù)交付逆巍、持續(xù)部署相關(guān)尺棋。個(gè)人對(duì)此的相關(guān)理解也再說下封锉。
現(xiàn)在很多大型公司的開發(fā)流程較為成熟完善,基本都需要做自動(dòng)化相關(guān)膘螟,而docker就能很方便地配合各種自動(dòng)化框架(jenkins成福、travis)進(jìn)行自動(dòng)化集成、部署荆残、運(yùn)行等奴艾。
關(guān)于持續(xù)集成、持續(xù)交付内斯、持續(xù)部署等概念蕴潦,這里個(gè)人簡(jiǎn)單做一下闡述
持續(xù)集成:以前是多個(gè)開發(fā)測(cè)試完畢后,才把代碼往主分支上合并俘闯,可能交叉潭苞、沖突,合并之后還可能產(chǎn)生新的問題备徐。而持續(xù)集成萄传,就是經(jīng)常提交代碼到主分支,一天可能好幾次蜜猾。并且秀菱,自動(dòng)化地進(jìn)行單元測(cè)試并提供測(cè)試報(bào)告等,這樣的話就能拆分細(xì)度顆粒蹭睡,保證產(chǎn)品能夠一步一步地安全可靠地迭代衍菱。很多以測(cè)試驅(qū)動(dòng)開發(fā)的公司就是這樣做的。
持續(xù)交付:持續(xù)集成的基礎(chǔ)上肩豁,增加打包構(gòu)建形成產(chǎn)物脊串。
持續(xù)部署:持續(xù)交付的基礎(chǔ)上辫呻,增加部署到相應(yīng)的線上環(huán)境。
總而言之琼锋,這些持續(xù)做的事情放闺,就是為了經(jīng)常提交代碼自動(dòng)化測(cè)試、運(yùn)行缕坎、部署怖侦,反饋問題,解決問題谜叹,再測(cè)試匾寝、運(yùn)行、部署依次循環(huán)荷腊。持續(xù)部署還有個(gè)好處艳悔,對(duì)我們個(gè)人網(wǎng)站來(lái)說,我們可以直接提交代碼女仰,后續(xù)一系列過程都是自動(dòng)化的猜年,就不用管了,它自己自動(dòng)部署發(fā)布董栽。
關(guān)于jenkins和travis码倦,jenkins是我個(gè)人比較推薦的,因?yàn)樗鷳B(tài)好锭碳、插件環(huán)境強(qiáng)、歷史悠久勿璃、穩(wěn)定擒抛;而travis,個(gè)人主要是練手嘗試补疑,他可以直接與github互聯(lián)歧沪,而我的代碼也是放在github上的,所以直接試試它莲组。
GPS定位系統(tǒng)系列
收獲
學(xué)習(xí)完這篇文章你將收獲:
- 無(wú)密ssh登錄服務(wù)器
- travis構(gòu)建
- 阿里云容器鏡像服務(wù)
- docker-compose
- travis.yml腳本邏輯
- 持續(xù)部署相關(guān)
[TOC]
正題
大體流程:
提交代碼->觸發(fā)github的hooks鉤子->travis自動(dòng)觸發(fā)->依照.travis.yml構(gòu)建環(huán)境诊胞,執(zhí)行腳本->完成部署
腳本大體邏輯:
1、travis openssl加密訪問服務(wù)器的私鑰锹杈,生成加密文件xxx.enc撵孤,在travis中解密形成其本地密鑰
2、項(xiàng)目maven打包
3竭望、docker構(gòu)建生成鏡像
4邪码、發(fā)布鏡像到阿里云容器鏡像
5、ssh訪問服務(wù)器(利用解密后的本地[指travis運(yùn)行環(huán)境]密鑰)咬清,執(zhí)行docker-compose完成部署
開發(fā)邏輯:
1闭专、綁定travis和github
2奴潘、無(wú)密登錄ssh,本地項(xiàng)目安裝travis影钉,加密密鑰
3画髓、阿里云開通容器鏡像服務(wù)
4、添加.travis.yml和Dockerfile文件
5平委、提交代碼
一雀扶、綁定travis和github
注意,travis現(xiàn)在有兩個(gè)網(wǎng)站肆汹,https://www.travis-ci.org和https://www.travis-ci.com
千萬(wàn)不要搞混了愚墓,org的是免費(fèi)的,對(duì)于github的開源項(xiàng)目免費(fèi)昂勉,com是收費(fèi)的浪册,不過對(duì)private的項(xiàng)目有構(gòu)建次數(shù)的限制。(我之前就是沒有注意org還是com岗照,結(jié)果發(fā)現(xiàn)村象,項(xiàng)目構(gòu)建,一直出問題攒至,iv nodefined
就是因?yàn)楹裾撸琣dd密鑰的解密環(huán)境變量到org去了,而com下面沒有迫吐,所以構(gòu)建失敗库菲,如圖)
1)直接sign in使用github賬號(hào)登錄,并授予權(quán)限
2)勾選開啟你要構(gòu)建的項(xiàng)目 即可
二志膀、無(wú)密登錄ssh熙宇,本地項(xiàng)目安裝travis,加密密鑰
按道理溉浙,一般自己都有了id_rsa和id_rsa.pub的密鑰烫止,路徑在~/.ssh/
下,這里我們?cè)賳为?dú)新建一個(gè)沒有密碼的密鑰
1)生成無(wú)密密鑰
cd ~/.ssh
ssh-keygen -t rsa
第一次輸入的是文件名:nopwd
第二次戳稽、第三次都輸入密碼馆蠕,我們是無(wú)密碼,所以直接回車
這樣就生成好了密鑰對(duì)惊奇,nopwd(私鑰)和nopwd.pub(公鑰)
2)上傳公鑰到服務(wù)器
sh-copy-id -i ~/.ssh/nopwd.pub root@你的服務(wù)器地址
3)安裝travis
換源
gem sources -l
gem sources --add https://gems.ruby-china.org/ --remove
安裝
sudo gem install travis
切換到項(xiàng)目目錄下
travis init
可能出現(xiàn)構(gòu)建失敗互躬,安裝依賴ruby-dev
sudo apt install ruby-dev
4)使用github賬號(hào)登錄travis
travis login --auto
如果本地有token或者github密鑰的話,就能直接登錄赊时。不然吨铸,就輸入賬號(hào)密碼
5)加密密鑰
travis encrypt-file ~/.ssh/nopwd --add
--add
會(huì)提示讓你加入一段解密密鑰的腳本到.travis.yml
文件中,如果有文件就會(huì)添加到文件里祖秒,沒有文件它給你創(chuàng)建或者你自己創(chuàng)建(travis init就會(huì)自動(dòng)創(chuàng)建)诞吱。
before_install: - openssl aes-256-cbc -K $encrypted_d51746e9182b_key -iv $encrypted_d51746e9182b_iv -in nopwd.enc -out ~/.ssh/nopwd -d
這就是要加入的內(nèi)容舟奠,-out ~/.ssh/xxx 這里你可以自己去名字,默認(rèn)是id_rsa房维,后面ssh登錄服務(wù)器會(huì)用到
其中encrypted_d51746e9182b_iv就是用來(lái)解密的
注意沼瘫,這里travis會(huì)上傳兩個(gè)環(huán)境變量encrypted_d51746e9182b_iv到服務(wù)器后臺(tái)去
當(dāng)然,環(huán)境變量的好處就是咙俩,你可以把.tavis.yml里面會(huì)用到的變量耿戚,都到這里來(lái)控制。
比如阿趁,你的addons添加的ip地址膜蛔,就可以這里來(lái)定義,然后文件里脖阵,就$ip來(lái)使用皂股。這樣,如果ip地址有變動(dòng)命黔,直接修改一下配置就可以了呜呐。
三、阿里云開通容器鏡像服務(wù)
阿里云 產(chǎn)品與服務(wù)中 找到【容器鏡像服務(wù)】然后悍募,添加鏡像蘑辑。當(dāng)然你也可以使用dockerhub來(lái)進(jìn)行鏡像的管理,不過速度可能沒有國(guó)內(nèi)的阿里云快坠宴。
這里我是web前端一個(gè)洋魂,java后端一個(gè)。
每個(gè)容器都可以管理不同版本的鏡像文件啄踊。
好了忧设,之后就有相關(guān)的文檔供配置使用。
四颠通、添加.travis.yml和Dockerfile文件
java后端項(xiàng)目配置
Dockerfile
在項(xiàng)目根目錄下,創(chuàng)建Dockerfile(以前在服務(wù)器端創(chuàng)建過膀懈,這里直接放到項(xiàng)目中來(lái)了)
# FROM adoptopenjdk/openjdk8:ubi
# openj9內(nèi)存會(huì)小很多
FROM adoptopenjdk:8-jdk-openj9
VOLUME /tmp
COPY target/demo-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
邏輯大致為:拉取jdk鏡像顿锰,拷貝項(xiàng)目生成的jar包到容器,運(yùn)行jar包
.travis.yml
language: java
services:
- docker
sudo: required
branches:
only:
- master
#使用ssh登陸的時(shí)候會(huì)確認(rèn)主機(jī)信息启搂,travis-ci自動(dòng)化運(yùn)行無(wú)法進(jìn)行交互操作硼控,所以在.travis.yml中添加以下內(nèi)容跳過確認(rèn)
addons:
ssh_known_hosts: $server_ip
before_install:
- openssl aes-256-cbc -K $encrypted_d51746e9182b_key -iv $encrypted_d51746e9182b_iv
-in nopwd.enc -out ~/.ssh/nopwd -d
script:
- mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
- docker build -t registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest .
after_success:
- docker login --username=jafir@1866908499405822 -p=$aliyun_pwd registry.cn-hangzhou.aliyuncs.com
- docker push registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest
- chmod 600 ~/.ssh/nopwd
- ssh -o "StrictHostKeyChecking no" -i ~/.ssh/nopwd root@$server_ip "cd /mydockerdata;docker-compose -f docker-compose.yml pull;docker-compose -f docker-compose.yml up -d;exit"
使用ssh登陸的時(shí)候會(huì)確認(rèn)主機(jī)信息,travis-ci自動(dòng)化運(yùn)行無(wú)法進(jìn)行交互操作胳赌,所以在.travis.yml中添加牢撼,
這里我們使用環(huán)境變量來(lái)控制,避免寫死疑苫。環(huán)境變量熏版,在travis的后臺(tái)settings里面添加
addons:
ssh_known_hosts: $server_ip
-t
后面則是你阿里云容器的鏡像地址纷责,可以設(shè)置版本,這里直接使用latest最新版
- docker build -t registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest .
登陸阿里云容器鏡像撼短,并推送鏡像
- docker login --username=jafir@1866908499405822 -p=$aliyun_pwd registry.cn-hangzhou.aliyuncs.com
- docker push registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest
這里跟文檔上有點(diǎn)不同,你可以直接-p
加入你自己的密碼,就不用輸入了恒界,密碼也是環(huán)境變量來(lái)配置aliyun_pwd
密鑰文件可能沒有權(quán)限踩蔚,給予權(quán)限
chmod 600 ~/.ssh/nopwd
ssh登錄服務(wù)器,執(zhí)行docker-compose拉取鏡像禾嫉,開啟服務(wù)
ssh -o "StrictHostKeyChecking no" -i ~/.ssh/nopwd root@47.108.82.91 "cd /mydockerdata;docker-compose -f docker-compose.yml pull;docker-compose -f docker-compose.yml up -d;exit"
-i ~/.ssh/nopwd
使用travsi系統(tǒng)中的密鑰登錄
docker-compose.yml
version: '2'
services:
mysql:
container_name: mysql1
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 數(shù)據(jù)庫(kù)密碼
ports:
- "3306:3306"
volumes:
- /usr/local/docker/mysql/data:/var/lib/mysql
- /usr/local/docker/mysql/conf:/etc/mysql
- /usr/local/docker/mysql/logs:/var/log/mysql
web:
container_name: jafir_nginx1
image: registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/web:latest
ports:
- 8080:80
restart: always
depends_on:
- java
volumes:
- /mydockerdata/nginx/etc/nginx.conf:/etc/nginx/nginx.conf
- /mydockerdata/nginx/log/:/var/log/nginx
java:
container_name: jafir_gps1
image: registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest
restart: always
depends_on:
- mysql
ports:
- 9090:9090
volumes:
- /mydockerdata/java/gps/upload:/Users/jafir/Downloads/upload
- /mydockerdata/arme/out/*.nofoo.cn/*.nofoo.cn.pfx:/Users/jafir/Downloads/upload/cert/*.nofoo.cn.pfx
我們這里直接使用docker-compose來(lái)啟動(dòng)3個(gè)服務(wù)灾杰,方便快捷。當(dāng)然熙参,你也可以單獨(dú)啟動(dòng)java一個(gè)容器艳吠。
邏輯也比較清晰
完成后提交代碼即可,不出意外的話就觸發(fā)travis的構(gòu)建尊惰,服務(wù)也能夠啟動(dòng)起來(lái)啦讲竿。
vue前端項(xiàng)目配置
Dockerfile
在項(xiàng)目根目錄下,創(chuàng)建Dockerfile
FROM nginx
COPY dist/ /usr/share/nginx/html/
邏輯大致為:拉取鏡像弄屡,拷貝項(xiàng)目靜態(tài)文件到nginx容器內(nèi)默認(rèn)的目錄
.travis.yml
language: js
services:
- docker
sudo: required
branches:
only:
- gps
addons:
ssh_known_hosts: $server_ip
before_install:
- openssl aes-256-cbc -K $encrypted_d51746e9182b_key -iv $encrypted_d51746e9182b_iv
-in nopwd.enc -out ~/.ssh/nopwd -d
script:
- npm run build
- docker build -t registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/web:latest .
after_success:
- docker login --username=jafir@1866908499405822 -p=$aliyun_pwd registry.cn-hangzhou.aliyuncs.com
- docker push registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-web:latest
- chmod 600 ~/.ssh/nopwd
- ssh -o "StrictHostKeyChecking no" -i ~/.ssh/nopwd root@$server_ip "cd /mydockerdata;docker-compose -f docker-compose.yml pull;docker-compose -f docker-compose.yml up -d;exit"
主要邏輯與上面的幾乎一致题禀。
不過要注意一點(diǎn):
以往我們都是通過上傳到服務(wù)器的dist目錄,再映射到 /usr/share/nginx/html
去的膀捷。而現(xiàn)在是迈嘹,直接把代碼打包到鏡像里面去,所以全庸,不需要再映射了秀仲,不然的話就會(huì)映射一個(gè)空目錄進(jìn)去了。
web:
container_name: jafir_nginx1
image: registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/web:latest
ports:
- 8080:80
restart: always
depends_on:
- java
volumes:
- /mydockerdata/nginx/etc/nginx.conf:/etc/nginx/nginx.conf
- /mydockerdata/nginx/log/:/var/log/nginx
volumes是只有配置文件的映射的壶笼,不需要項(xiàng)目目錄的映射神僵。
五、提交代碼覆劈,成功
隨意提交一下代碼保礼,就能看到服務(wù)器的docker-compose的項(xiàng)目啟動(dòng)起來(lái)啦!
travis的控制臺(tái)也能看到構(gòu)建成功啦责语。
關(guān)于作者
作者是一個(gè)熱愛學(xué)習(xí)炮障、開源、分享坤候,傳播正能量胁赢,喜歡打籃球、頭發(fā)還很多的程序員-白筹。-
熱烈歡迎大家關(guān)注智末、點(diǎn)贊谅摄、評(píng)論交流!
簡(jiǎn)書:http://www.reibang.com/u/d234d1569eed
github:https://github.com/fly7632785