本篇部署不是叢集部署,適合個人或小公司專案使用。
GitHub由於是國外平臺,程式碼拉取速度不是特別理想。所以使用了CODING作為程式碼託管平臺。
Hyperf是一款Swoole框架,如果是Mac開發可以直接在宿主機安裝Swoole擴充套件進行開發,如果在Mac上使用Docker的話速度會變慢。
如果用windows開發,可以使用WSL2,安裝Docker進行開發。不過感覺還是慢,推薦使用PhpStorm的Deployment服務直接使用檔案自動上傳伺服器,然後在伺服器安裝Docker環境進行開發。
建立基礎專案
- 首先我們點選右上角,建立一個專案
進入專案後點選右上角,建立一個程式碼倉庫
- 安裝 Hyperf
安裝方式
然後和我們剛剛建立的遠端倉庫關聯(預設大家都有這個能力)
編寫構建計劃
這裡先大概說下我們整體的部署流程。
首先檢出分支,然後會根據分支下的Dockerfile生成映象,然後推送映象到coding的製品倉庫。最後登入伺服器拉取映象進行部署。
流程清楚了那麼我們就開始編寫構建計劃吧
- 建立構建計劃
首先我們先建立一個構建計劃,構建計劃就是弄一套指令,讓它按照我們自己設定的規則執行
然後選擇構造計劃模板,我們這裡選擇自定義模板
按照預設配置即可,這裡我們先使用線上的Jenkinsfile,後續可以根據自己需求使用程式碼倉庫中的Jenkinsfile
開始進行流程配置
生成映象並推送
pipeline { agent any stages { stage("檢出") { steps { checkout([ $class: 'GitSCM', branches: [[name: GIT_BUILD_REF]], userRemoteConfigs: [[ url: GIT_REPO_URL, credentialsId: CREDENTIALS_ID ]]]) } } stage('生成映象') { steps { echo '生成映象中……' sh 'ls' sh 'docker build -t ${IMAGE_NAME} -f Dockerfile ./' echo '生成映象完成' } } stage('推送映象') { steps { echo '推送映象中...' sh 'docker login -u image-xxxx -p ${DOCKER_TOKEN} xxx-docker.pkg.coding.net' sh 'docker tag ${IMAGE_NAME} xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}' sh 'docker push xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}' echo '推送完成' } } } }
我們先來看生成映象,因為Hyperf官方已經在專案中寫好了Dockerfile,我們可根據自己需求更改直接使用就好。很簡單就是執行了一個docker命令,但是裡面有一個映象名,這個我們拿出來定義一個變數然後在檔案中就可以通過
${IMAGE_NAME}
這種方式來訪問了。
定義變數:
映象生成了,往哪兒推送?別急,我們先儲存構建計劃。
然後新建一個製品庫,就是存放我們docker映象的地方
建立成功後,如圖
然後複製倉庫中的登入和推送命令配置到我們構造計劃檔案中
我們這裡選擇使用令牌的方式進行登入,點選這個按鈕,複製生成的令牌。替換剛才的登入命令
由於登入密碼是敏感的,我們按照第一次建立環境變數的方式再次新增一個變數${DOCKER_TOKEN}
替換登入密碼
到此為止,其實已經完成專案自動生成映象並上傳倉庫。已經可以在伺服器手動Docker映象拉取部署了。(伺服器需要已安裝Docker,不然玩兒毛)
- 自動部署
stage('部署') {
steps {
echo '部署中...'
script {
def remote = [:]
remote.name = 'my-server'
remote.allowAnyHosts = true
// 主機地址
remote.host = '123.123.123.132'
remote.port = 22
// 使用者名稱
remote.user = 'root'
// credentialsId: coding登入主機的祕鑰
withCredentials([sshUserPrivateKey(credentialsId: 'coding的key', keyFileVariable: 'id_rsa')]) {
remote.identityFile = id_rsa
// 登入並拉取映象
sshCommand remote: remote, command: "docker login -u image-xxxx -p ${DOCKER_TOKEN} xxx-docker.pkg.coding.net"
sshCommand remote: remote, command: "docker pull xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}:latest"
// 停止舊的服務,注意加 ||true,不然第一次部署會報錯
sshCommand remote: remote, command: "docker stop ${PROJECT_NAME} || true"
sshCommand remote: remote, command: "docker rm ${PROJECT_NAME} || true"
// 啟動新服務
sshCommand remote: remote, command: "docker run -d --restart always -p 10090:9501 -v /www/go_pocket_api.env:/opt/www/.env --name ${PROJECT_NAME} -d xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}:latest"
// 再啟動一個容器,防止服務中斷
sshCommand remote: remote, command: "docker stop ${PROJECT_NAME}2 || true"
sshCommand remote: remote, command: "docker rm ${PROJECT_NAME}2 || true"
sshCommand remote: remote, command: "docker run -d --restart always -p 10091:9501 -v /www/go_pocket_api.env:/opt/www/.env --name ${PROJECT_NAME}2 -d xxx-docker.pkg.coding.net/practice/practice/blog/${IMAGE_NAME}:latest"
}
}
echo '部署完成'
}
}
上部分配置參考了Hyperf作者文章
如何單機部署 Hyperf 專案
上面我們注意有個credentialsId,這個是coding能登入我們伺服器的關鍵。這個東西會在condig讀取祕鑰,然後使用祕鑰登入我們的伺服器進行操作。
所以伺服器需要支援ssh祕鑰登入。
生成方式:
點選專案設定:
然後錄入憑據,最後使用憑據id填入上面的credentialsId
錄入憑據的方法
最後我們還需要配置觸發規則,也就是什麼情況執行部署。推送到master,或者推送新標籤後觸發。
還有一點需要注意,由於自動部署需要訪問我們的docker映象倉庫。所以我們需要把執行構建的伺服器IP新增到docker映象倉庫的白名單裡面。
(因為我們使用的免費的,所以使用了coding自己的伺服器,基本夠用。不夠用可以夠買coding提供的構建伺服器。好像也不貴。)
首先複製構建伺服器ip
寫入到白名單
然後新增兩個IP到白名單
儲存即可
完整版Jenkinsfile
pipeline {
agent any
stages {
stage("檢出") {
steps {
checkout([
$class: 'GitSCM',
branches: [[name: GIT_BUILD_REF]],
userRemoteConfigs: [[
url: GIT_REPO_URL,
credentialsId: CREDENTIALS_ID
]]])
}
}
stage('生成映象') {
steps {
echo '生成映象中……'
sh 'ls'
sh 'docker build -t ${IMAGE_NAME} -f Dockerfile ./'
echo '生成映象完成'
}
}
stage('推送映象') {
steps {
echo '推送映象中...'
sh 'docker login -u image-xxxx -p ${DOCKER_TOKEN} xxx-docker.pkg.coding.net'
sh 'docker tag ${IMAGE_NAME} xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}'
sh 'docker push xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}'
echo '推送完成'
}
}
stage('部署') {
steps {
echo '部署中...'
script {
def remote = [:]
remote.name = 'my-server'
remote.allowAnyHosts = true
// 主機地址
remote.host = '123.123.123.132'
remote.port = 22
// 使用者名稱
remote.user = 'root'
// credentialsId: coding登入主機的祕鑰
withCredentials([sshUserPrivateKey(credentialsId: 'coding的key', keyFileVariable: 'id_rsa')]) {
remote.identityFile = id_rsa
// 登入並拉取映象
sshCommand remote: remote, command: "docker login -u image-xxxx -p ${DOCKER_TOKEN} xxx-docker.pkg.coding.net"
sshCommand remote: remote, command: "docker pull xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}:latest"
// 停止舊的服務,注意加 ||true,不然第一次部署會報錯
sshCommand remote: remote, command: "docker stop ${PROJECT_NAME} || true"
sshCommand remote: remote, command: "docker rm ${PROJECT_NAME} || true"
// 啟動新服務
sshCommand remote: remote, command: "docker run -d --restart always -p 10090:9501 -v /www/go_pocket_api.env:/opt/www/.env --name ${PROJECT_NAME} -d xxx-docker.pkg.coding.net/practice/blog/${IMAGE_NAME}:latest"
// 再啟動一個容器,防止服務中斷
sshCommand remote: remote, command: "docker stop ${PROJECT_NAME}2 || true"
sshCommand remote: remote, command: "docker rm ${PROJECT_NAME}2 || true"
sshCommand remote: remote, command: "docker run -d --restart always -p 10091:9501 -v /www/go_pocket_api.env:/opt/www/.env --name ${PROJECT_NAME}2 -d xxx-docker.pkg.coding.net/practice/practice/blog/${IMAGE_NAME}:latest"
}
}
echo '部署完成'
}
}
}
}
需要注意,執行前需要先建立好env檔案,因為Docker掛載時如果原始檔不存在會自動建立目錄。參考Docker掛載檔案不存在情況
.env檔案沒想好有什麼自動不需要建立的方式,寫入到映象環境變數中??
大家有好的思路可以交流
然後我們本地修改程式碼,推送到master或者推送標籤根據自己設定的觸發規則來。神奇的事情發生了。
Nginx配置
upstream test {
server 127.0.0.1:10090;
server 127.0.0.1:10091;
}
server {
listen 80;
server_name www.xxx.com;
location / {
proxy_pass http://test;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
到此,部署完成。
本作品採用《CC 協議》,轉載必須註明作者和本文連結