使用Github Actions + Watchtower 實現專案CI/CD
前言
對於我們這種個人開發者,將程式部署在伺服器上一般都是透過寶塔部署來確保服務能夠一直存活,但是對於一個經常改來改去的專案,這是一個非常頭疼的事情,需要重複地本地編譯-->開啟寶塔-->輸入賬號密碼(甚至安全模式無法記住密碼,需要自己輸入密碼)-->上傳檔案-->重啟程式碼服務。
對於一個聰明的程式設計師來說,一切重複的工作都應該交給程式碼來執行,恰巧前幾天,在寫公司專案的時候,我的導師跟我說改完的程式碼直接push到github的test分支,等待幾分鐘程式碼就部署好了,這不正是我想要的自動化嗎,之後查了一下這個叫專案CI/CD,公司使用的技術有Github Actions,Dokcer容器,Watchtower,來實現程式碼自動部署的,注意,這類技術在Watch Tower官方文件中明確寫出,不建議在生產環境中使用該技術,即使他會在有新版本可以更新時,優雅地關閉正在執行的程式,但可能造成重大安全事故。
本文會從編寫Dockerfile入手,學習如何推送映象,如何編寫workflow檔案編寫github工作流,之後配置watchtower實現程式碼自動更新。
本文需要前置知識:docker相關操作,Dockerfile編寫。
元件介紹
首先先理解幾個概念。
專案CI/CD
在網際網路開發中,CI 和 CD 是兩個常用的縮寫詞,分別代表持續整合(Continuous Integration)和持續交付/持續部署(Continuous Delivery/Continuous Deployment)。
持續整合(Continuous Integration,CI):
持續整合是一種開發實踐,旨在透過頻繁地將程式碼合併到主幹分支,並進行自動化構建、測試和部署等操作,以確保團隊成員的工作能夠快速且無衝突地整合到共享程式碼庫中。CI 的目標是儘早發現和解決程式碼整合問題,並提供可靠的構建和測試過程,以減少整合帶來的風險。
在 CI 中,開發者在完成某項工作後,會將程式碼變更提交到版本控制系統(如 Git),觸發自動化構建和測試流程。這些流程通常包括編譯程式碼、執行單元測試、進行靜態程式碼分析等。如果構建和測試透過,程式碼變更就可以合併到共享程式碼庫,否則需要開發者修復問題。
持續交付/持續部署(Continuous Delivery/Continuous Deployment,CD):
持續交付和持續部署是指在 CI 的基礎上,透過自動化流程將經過驗證的程式碼變更交付給生產環境。
持續交付(Continuous Delivery):持續交付意味著程式碼變更透過了構建和測試,並已經準備好進行部署,但是部署的時機由人工決定。在持續交付中,開發團隊可以隨時選擇將已驗證的程式碼釋出到生產環境,以快速響應使用者需求或滿足業務的要求。
持續部署(Continuous Deployment):持續部署是在持續交付的基礎上更進一步,自動化地將經過驗證的程式碼變更直接部署到生產環境,無需人工干預。在持續部署中,如果程式碼透過了構建和測試,它將立即被部署到生產環境,從而實現快速的軟體釋出。
總結來說,CI 是一種開發實踐,旨在幫助團隊更好地整合和驗證程式碼,而 CD 則進一步強調了對程式碼變更的自動化交付和部署。持續整合和持續交付/持續部署的實踐能夠提高開發效率、減少錯誤,並使團隊能夠更快地交付高質量的軟體產品。
Github Actions
GitHub Actions 是一個持續整合(Continuous integration)和持續交付(Continuous delivery)的平臺,它可以做到自動化構建、測試、部署。你可以建立工作流,構建和測試每一個 pull request 或者部署合併後的程式碼到生產環境。GitHub Actions 可以在你的程式碼倉庫發生某個事件時執行一個工作流。舉個例子,當有人給你的專案提出issue時,可以自動通知團隊成員等。GitHub 提供了 Linux、Windows、和 macOS 虛擬機器執行你的工作流,當然你也可以自定義執行環境。
在本文中主要用於使用Github Actions來進行專案CI,當有程式碼提交到指定分支時,會自動打包容器映象並推送到docker hub,用於更新映象倉庫的映象。
Docker容器
一種輕量級的虛擬化技術,也是目前主流的應用部署策略
Docker容器**是一種輕量級的虛擬化技術,使用開源的應用容器引擎。
這種技術可以讓開發者將應用及其依賴打包到一個可移植的容器中,然後釋出到任何安裝了Docker引擎的伺服器上,這些伺服器可以是流行的Linux或Windows機器,Docker容器提供了一種比傳統虛擬機器更輕量化的虛擬化方式,具有安裝便捷、啟停速度快的特點。
容器之間是完全隔離的,使用沙箱機制,相互之間不會有任何介面,這種隔離機制基於Linux核心的控制組(Cgroups)和名稱空間(Namespaces)技術。
容器映象是一種輕巧、可執行的獨立軟體包,包含執行應用程式所需的一切,如程式碼、執行時環境、系統工具、系統庫和設定。這些映象在執行時成為容器,使得軟體具有獨立性,免受外在環境差異的影響,並有助於減少在不同基礎設施上執行不同軟體時的衝突。
在本文中,應用程式主要使用docker容器部署,並使用docker hub作為儲存倉庫。
Watchtower
[Watchtower][https://github.com/containrrr/watchtower] 是一款自由開源的應用,用來監控執行中的Docker 容器,並且當它發現基礎映象被更改後,可以自動的更新容器。 若Watchtower 發現一個執行中的容器需要更新,它會以傳送SIGTERM 訊號的方式,優雅的結束執行中容器的執行。 它會下載新映象,然後以最初部署時使用的方式,重啟容器。
在本文中,主要使用watch tower來做映象更新與應用重啟。
編寫一個應用程式
根據自己需要編寫程式
編寫Dockerfile檔案
編寫專案需要的Dockerfile
檔案。
在Github倉庫新建一個workflow檔案
- 在Github的倉庫中有一欄Actions,點選
New workflow
,會看到幾個Github 預設的幾個模型,這裡選擇Docker image
這裡附上我的配置
name: Docker Image CI
on:
push:
branches: [ "main" ] #當有push到main分支時
jobs:
build:
runs-on: ubuntu-latest #執行在虛擬機器環境 ubuntu-latest
steps:
- uses: actions/checkout@v3 #獲取原始碼 使用的 action 是actions/checkout@v3
- name: Build the Docker image #要執行job的名稱 可自定義
run: | #開始執行
cd app/ #我的Dockerfile檔案所在目錄
docker login -u yjddb -p ${{ secrets.DOCKER_HUB_PASSWORD }} #登入docker hub 括號內為插值表示式,用於保護docker hub密碼
docker buildx create --use #使用docker buildx 比docker build功能更加強大一點
docker buildx build . --push --tag yjddb/compete_cloud_app_back:latest #構建映象並推送到指定倉庫,tag設定為latest
- 編寫完
workflow
檔案之後還需要把自己的docker密碼儲存在倉庫中。
編寫的秘鑰名稱需要與dockerfile中一樣才可以正常被使用
- 至此github的ci工作流已經建立完成,這時候可以自己在main分支改動提交即可在actions欄中看到CI工作流。
程式碼可以正常編譯之後即可推送到相關dockerhub上面。
使用Watch Tower 自動更新映象
-
在伺服器上安裝docker
-
在自己的伺服器上面 docker pull 下來自己的映象 然後用 正確的命令方式啟動映象
-
執行docker命令拉下來映象並啟動自動更新
docker run -d \ --name watchtower \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --interval 30 \ #每隔30s查詢一次最新映象版本 nginx redis #更新指定容器 --cleanup \ #清理標籤為none的映象。 --remove-volumes \ #清理匿名卷
如果不加映象指定會監控當前正在執行容器的映象,當有新的映象在docker hub更新時會自動更新映象,--interval 30代表每隔30秒進行一次檢視更新操作,不指定的話預設60s ,更多配置請檢視官方文件
結語
至此,就可以愉快的寫程式碼了,沒有部署專案的煩惱了。