我們使用Gitea搭建了自己的Git版本控制系統,可以用來管理自己的代碼還需要一個自動構建工具來解放生產力,這裡我推薦使用Drone來搭建CI/CD持續集成,持續部署平臺 為什麼選用Gitea+Drone呢?因為這兩款軟體都是基於go編寫的,運行過程中可謂十分輕量級,對於資源的佔用都是很少的,並且都可以基於docker來安裝,安裝部署起來十分方便相對來說主流的Gitlab+Jenkins一套下來對於資源的佔用,個人是很難能流暢運行的,至少我的機器連個Gitlab都跑不起來,更別提使用Java編寫的Jenkins了。。。 廢話少說,直接開搞~ 這裡我的伺服器環境使用的是最新的CentOS7 x64系統,只安裝了一個docker
1 安裝Gitea
Gitea的安裝過程詳見:https://ffis.me/experience/1960.html這裡就不做過多的闡述了
2 安裝Drone
新版的Drone可以直接使用OAuto2和drone進行通信,無縫集成,配置完成後只需要得到gitea的授權即可進入drone平臺,連帳戶和密碼都不用輸了
2.1 Gitea創建OAuth2應用程式
我們進入Gitea-->點擊右上角頭像-->設置-->應用-->管理OAuth2應用程式來創建一個OAuth2應用程式
這裡的重定向URL是授權成功後跳轉到drone的地址,根據自己的drone地址來創建
創建成功後就可以拿到客戶端ID和客戶端密鑰了,這裡可以先記錄下來,我們後邊會用到,因為一旦離開這個頁面就沒法再查看密鑰了,只能重新生成
2.2 創建共享密鑰
這裡我們還需要創建一個共享密鑰來供drone和docker-runner通信使用我們可以使用openssl生成共享密鑰:
$ openssl rand -hex16da7fb75c68106b563100bec5ce166b72
2.3 安裝Docker Compose
這裡我使用Docker Compose來部署DroneDocker Compose是用來批量創建和管理Docker容器的,只需要配置好yml配置文件,就可以批量管理Docker容器安裝過程可參考:https://www.runoob.com/docker/docker-compose.html
2.4 編寫docker-compose.yml文件
這裡我們通過使用 Docker Compose 來構建並啟動 Drone和 Docker Runner,編寫 docker-compose.yml 文件
$ mkdir drone$cd drone$ vim docker-compose.yml
在配置文件中,我們設置 docker-compose.yml 的格式為 3 號版本,定義以下兩個docker服務。
Drone Server:使用drone/drone:1版本鏡像,將 drone 容器的 80 埠映射到宿主機的 7079 埠。映射容器內 /data 目錄到宿主機的 /data/drone 目錄,以便 drone 可以保留數據。配置服務自動重新啟動,並配置構建 drone 所需的環境變量。Docker Runner:使用 drone/drone-runner-docker:1 版本鏡像,將 docker 啟動句柄掛載到容器 /var/run/docker.sock 文件中,以便 drone 可以使用 docker-runner 來執行鏡像構建任務。環境變量中需要配置 drone server 的埠協議以及共享密鑰,以便與 server 進行通信。具體配置可參考如下配置:
version: '3'services: # 容器名稱fan-drone-server: # 構建所使用的鏡像image: drone/drone:1 # 映射容器內80埠到宿主機的7079埠ports:-7079:80 # 映射容器內/data目錄到宿主機的/data/drone目錄volumes:-/data/drone:/data # 容器隨docker自動啟動restart: alwaysenvironment: # Gitea 伺服器地址-DRONE_GITEA_SERVER=https://git.ffis.me # Gitea OAuth2客戶端ID-DRONE_GITEA_CLIENT_ID=aaaaaaaaaaa-8888-8888-8888-fffffffffffff # Gitea OAuth2客戶端密鑰-DRONE_GITEA_CLIENT_SECRET=aaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbffffffff # drone的共享密鑰-DRONE_RPC_SECRET=asdfsadfasdfsadfsadfasdf # drone的主機名-DRONE_SERVER_HOST=drone.ffis.me # 外部協議方案-DRONE_SERVER_PROTO=https # 創建管理員帳戶,這裡對應為gitea的用戶名-DRONE_USER_CREATE=username:noisky,admin:truefan-docker-runner:image: drone/drone-runner-docker:1ports:-7080:3000restart: alwaysdepends_on:-fan-drone-servervolumes:-/var/run/docker.sock:/var/run/docker.sockenvironment: # 用於連接到Drone伺服器的協議。該值必須是http或https。-DRONE_RPC_PROTO=https # 用於連接到Drone伺服器的主機名-DRONE_RPC_HOST=drone.ffis.me # Drone伺服器進行身份驗證的共享密鑰,和上面設置一樣-DRONE_RPC_SECRET=asdfsadfasdfsadfsadfasdf # 限制運行程序可以執行的並發管道數。運行程序默認情況下執行2個並發管道。-DRONE_RUNNER_CAPACITY=2 # docker runner 名稱-DRONE_RUNNER_NAME=fan-docker-runner-1
2.5 構建drone和runner
docker-compose up -d-d 為後臺運行
這裡我的drone使用的域名訪問,是因為我配置了nginx反向代理,如果你沒有配置也可以使用ip:埠的形式訪問,一定要配置好域名再進行構建,不然會報錯貼出我的drone的nginx反向代理配置,供參考
location / {proxy_pass http://127.0.0.1:7079/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header REMOTE-HOST $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
2.6 打開drone
到這裡如果沒有出問題的話drone就構建完成了,我們在瀏覽器輸入配置的drone地址,可看到自動跳轉到gitea的授權頁面
這裡我們進行授權後就跳轉到drone的頁面了,只需授權一次即可,往後我們登錄了gitea就直接進入drone了
進入drone會看到未激活的倉庫,我們點擊激活它
激活後回到gitea,我們會看到倉庫已經自動配置好了web鉤子
我們可以進去測試鉤子,一般是沒問題的
到這裡我們的drone就安裝完畢了,激活倉庫後,我們向倉庫推送一個commit,gitea就會發送消息通知drone去幹活啦~
3 配置Drone自動構建
drone的安裝過程還是很簡單的,下面我們來進行drone構建的配置drone支持不同環境的不同管道配置,這裡我使用Docker Pipelines管道配置簡單來說就是drone的每一步操作都在一個臨時的drone的容器中進行,容器操作完會自動銷毀,容器之間會共享當前的工作目錄
這裡我還是構建一個springboot工程,下面介紹兩種部署方式:
3.1 本地部署
本地部署主要步驟:
drone拉取最新的代碼到當前工作目錄drone創建maven/grade容器,通過指定的構建工具maven/grade等將代碼編譯/打包為jar包,然後將jar包和Dockerfile文件複製到掛載的宿主機共享目錄中drone創建ssh容器,在容器中通過ssh連接到宿主機,通過定義好的命令,到jar和Dockerfile目錄中將jar包製作構建為鏡像,然後通過鏡像創建應用容器並運行,期間會刪除之前老的應用程式容器和鏡像drone創建釘釘通知容器,將構建成功/失敗的消息通過釘釘機器人通知到管理員至此本地構建完畢,這個構建步驟是我自己搞的,其優點是所有操作都在本機執行,構建的應用不用經過網絡傳輸,整體部署的速度很快,其缺點是只能單機部署,無法進行分布式多機器部署,如果自己個人單機使用的話推薦使用這種方式,我的測試demo,整體部署流程下來只用了12s,速度還是很快的
編寫drone部署的文件
在倉庫的根目錄下創建.drone.yml配置文件配置文件參考如下配置:
# drone 本地構建kind: pipelinetype: dockername: MyHelloWorld# drone構建步驟steps: # 1.maven打包-name: maven compilepull: if-not-existsimage: maven:ibmjava-alpinevolumes: # maven構建緩存-name: cachepath: /root/.m2 # 掛載宿主機的目錄-name: datapath: /homecommands: # 開始打包maven工程-cd demo-mvn clean package -Dmaven.test.skip=true # 將打包後的文件複製到宿主機映射目錄-cp target/*.jar /home-cp ../Dockerfile /home # 2.使用ssh訪問主機製作鏡像並運行-name: ssh commandspull: if-not-existsimage: appleboy/drone-ssh:1.5.7settings:host: 0.0.0.0username: rootpassword: # 從drone倉庫配置中秘密空間讀取密碼from_secret: ssh_passwordport: 22script:-echo =======暫停容器=======-docker stop `docker ps -a | grep springdemo | awk '{print $1}' `-echo =======暫停舊容器和鏡像=======-docker rm -f `docker ps -a | grep springdemo | awk '{print $1}' `-docker rmi `docker images | grep springdemo | awk '{print $3}' `-echo =======開始構建新鏡像=======-cd /data/drone/helloDemo-docker build -t springdemo:v1 .-echo =======開始部署應用=======-docker run -d -p 8188:8180 --name springdemo springdemo:v1-echo =======清理構建文件=======-rm -rf *-echo =======部署成功======= # 3.釘釘通知-name: dingTalk notificationpull: if-not-existsimage: guoxudongdocker/drone-dingtalk:latestsettings:token:from_secret: dingtalk_tokentype: markdownmessage_color: truemessage_pic: truesha_link: truewhen:status: [failure, success]# 掛載的主機卷,可以映射到docker容器中volumes: # maven構建緩存-name: cachehost: # path: /tmp/cache/.m2path: /var/lib/cache # maven構建後與宿主機通信的共享目錄-name: datahost:path: /data/drone/helloDemo# drone執行觸發器trigger:branch:-master
文件編寫完成後,git push到倉庫中,gitea會通知drone進行部署,drone找到.drone.yml配置文件,就會按照配置文件中的步驟進行構建了,部署期間可以在drone中查看到每一步的部署情況
3.2 分布式雲部署
雲部署主要步驟:
drone拉取最新的代碼到當前工作目錄drone創建maven/grade容器,通過指定的構建工具maven/grade等將代碼編譯/打包為jar包,然後將打包完成後的jar移動到根目錄,也就是工作目錄drone創建docker構建容器,將jar通過dockerfile指定的方式構建為鏡像,然後將構建完成的鏡像上傳到騰訊雲/阿里雲私有倉庫中drone創建ssh容器,通過ssh連接到一個或多個主機,然後批量從私有倉庫中拉取最新鏡像進行部署drone創建釘釘通知容器,將構建成功/失敗的消息通過釘釘機器人通知到管理員這種方式配置較為簡單,所有操作都在docker中進行,沒有和主機通訊,並且構建好的鏡像直接推送到第三方私有倉庫中的,期間會通過網絡傳輸,多多少少都會耗費點時間;不過好在同一服務商的私有倉庫都是通過內網進行訪問的,訪問速度影響可忽略不計;而且有很大的優化空間,畢竟我們寫的代碼只有幾百k的大小,其中的系統層、jdk層、lib依賴庫層,基本上代碼都是不變的;所以可以通過對docker鏡像進行分層構建,分層推送,通過緩存的加速也是可以做到秒級推送,這樣每次更新的就只有我們寫的代碼,傳輸的數據量就很少了,不過這個屬於比較高級的應用了,我們這裡先不研究了;雲部署主要好處是可以做到分布式部署,多個主機可以從私有倉庫中拉取最新鏡像,實用性還是很高的。
編寫drone部署的文件同樣也是在倉庫的根目錄下創建.drone.yml配置文件參考如下配置:
# drone 雲部署kind: pipelinetype: dockername: MyHelloWorld# drone構建步驟steps: # 1.maven打包-name: maven compilepull: if-not-existsimage: maven:ibmjava-alpinevolumes: # maven構建緩存-name: cachepath: /root/.m2commands: # 開始打包maven工程-cd demo-mvn clean package -Dmaven.test.skip=true # 將打包後的jar包移動到 Dockerfile 文件同級目錄-mv target/demo-0.0.1-SNAPSHOT.jar ../demo-0.0.1-SNAPSHOT.jar # 2.Docker 製作鏡像,推送到私有倉庫-name: docker buildimage: plugins/dockerpull: if-not-existsvolumes:-name: dockerpath: /var/run/docker.socksettings:username: usernamepassword:from_secret: dockerHub_passwordtags:-latestrepo: ccr.ccs.tencentyun.com/fanfan/hellodemoregistry: ccr.ccs.tencentyun.comdockerfile: Dockerfile # 3.使用ssh訪問主機運行最新版容器-name: ssh commandspull: if-not-existsimage: appleboy/drone-ssh:1.5.7settings:host: 49.234.106.44username: rootpassword:from_secret: ssh_passwordport: 22script:-echo =======暫停容器=======-docker stop `docker ps -a | grep springdemo | awk '{print $1}' `-echo =======暫停舊容器=======-docker rm -f `docker ps -a | grep springdemo | awk '{print $1}' `-echo =======開始部署應用=======-docker run -d -p 8188:8180 --name springdemo --restart=always ccr.ccs.tencentyun.com/fanfan/hellodemo:latest-echo =======部署成功======= # 4.釘釘通知-name: dingTalk notificationpull: if-not-existsimage: guoxudongdocker/drone-dingtalk:latestsettings:token:from_secret: dingtalk_tokentype: markdownmessage_color: truemessage_pic: truesha_link: truewhen:status: [failure, success]# 掛載的主機卷,可以映射到docker容器中volumes: # maven構建緩存-name: cachehost: # path: /tmp/cache/.m2path: /var/lib/cache-name: dockerhost:path: /var/run/docker.sock# drone執行觸發器trigger:branch:-master
編寫好部署的配置文件,推送到倉庫中,drone就行按照配置的步驟進行部署了首次部署的速度可能略慢,我這裡用了50s,不過等倉庫緩存變熱之後速度就上來了,這裡我用了33s
總體很是可以接受的,如果進行分層構建優化的話,應該還會再快,不過還是和本地部署的速度沒得比,這裡根據自己的需要選擇不同的部署方式即可,並且不同語言的應用部署的方式是不一樣的,可以定製屬於自己的部署方式
部署成功後的釘釘通知頁面
4 資源佔用
Gitea和Drone都是基於go語言編寫的,其優點是輕量級,佔用資源較少,下面為部署了gitea和drone後的資源佔用
可以看到總佔用也不到200M的內存,相比傳統的gitlab+Jenkins非常輕量化了,並且該有的功能都有,如果用戶數不是很大的話,還是很推薦大家使用的
自動部署一旦配置好了,所有的編譯/測試/打包/部署的工作就交給drone去完成了,而我們只需要專注於我們的代碼編寫就行了,是不是特別爽呢?還不快去搭建一個屬於自己的自動構建平臺吧~
https://www.ffis.me/archives/1988.html
-深入原理-
知其然並知其所以然