分享程式代碼相關筆記
目前文章總數:157 篇
最後更新:2024年 12月 07日
Putty官網,對於什麼是 Putty? 官方給的回覆如下:
A.1.1 What is PuTTY?
PuTTY is a client program for the SSH, Telnet, Rlogin, and SUPDUP network protocols.
These protocols are all used to run a remote session on a computer, over a network. PuTTY implements the client end of that session: the end at which the session is displayed, rather than the end at which it runs.
In really simple terms: you run PuTTY on a Windows machine, and tell it to connect to (for example) a Unix machine. PuTTY opens a window. Then, anything you type into that window is sent straight to the Unix machine, and everything the Unix machine sends back is displayed in the window. So you can work on the Unix machine as if you were sitting at its console, while actually sitting somewhere else.
簡單說就是安裝 Putty 軟體後,可以很輕鬆的對遠端 Linux 主機透過 ssh 連線
我們目的是要讓 Jenkins 主機可以對遠端的 Linux 操作 Docker Compose 指令
Putty 並沒有收費,而且是一個開源軟體 PuTTY License
甚至可以自己下載原始碼,調整代碼,用於商業行為、目的。
進入下載頁後
選擇自己系統的所需版本
下載後可進行安裝,基本上都下一步
安裝完成後,記錄下 plink.exe 的路徑,Jenkins 只需要用指令的方式即可
C:\Program Files\PuTTY\plink.exe
為了實現自動化部署,需要將專案簽入到版控中
DockerFile 一併簽入,可透過 SShPublish 工具傳送
Pipeline 完整語法如下:
※一共 8 部分
pipeline {
agent any
stages {
// 1. 從 Gitlab 上 Pull 代碼
stage('Checkout') {
steps {
withCredentials([usernamePassword(credentialsId: "${params.GIT_CREDENTIALS}", passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
checkout([$class: 'GitSCM', branches: [[name: 'remotes/origin/main']], userRemoteConfigs: [[url: 'http://{你的Git網站}/testweb.git']]])
bat """
git pull origin main
"""
bat """
git checkout ${params.GIT_HASH_TAG}
"""
}
}
}
// 2. 從 Jenkins 建置代碼
stage('Building') {
steps {
script {
bat """
path C:/Program Files/dotnet/
dotnet publish Src/WebCoreTest.csproj -c Release -o Src/publish/WebCoreTest
"""
}
}
}
// 3. 將建置後的發布包部署到 Linux 機器上
stage('Publish') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: '192.168.1.100(LinuxSite)', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'dockerbuildimage\\WebCoreTest\\publish', remoteDirectorySDF: false, removePrefix: 'Src\\publish\\WebCoreTest', sourceFiles: 'Src\\publish\\WebCoreTest\\**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
// 4. 將DockerFile 檔案複製到 Linux 機器上
stage('Publish DockerFile') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: '192.168.1.100(LinuxSite)', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'dockerbuildimage\\WebCoreTest', remoteDirectorySDF: false, removePrefix: 'Src\\WebCoreTest', sourceFiles: 'Src\\WebCoreTest\\Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
// 5. (可跳過) 驗證遠端機器是否存活,並且確認 Putty 可用
stage('Connect') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: "${params.DEV_TESTSITE_CREDENTIALS}", keyFileVariable: 'SSH_PRIVATE_KEY', passphraseVariable: 'SSH_PASSPHRASE', usernameVariable: 'SSH_USERNAME')]) {
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.51.100 -pw ${SSH_PASSPHRASE} "echo Connected to 192.168.1.100 server"
"""
}
}
}
// 6. 建立 Docker Image ,並且存放於遠端機器上
stage('Build Image') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: "${params.DEV_TESTSITE_CREDENTIALS}", keyFileVariable: 'SSH_PRIVATE_KEY', passphraseVariable: 'SSH_PASSPHRASE', usernameVariable: 'SSH_USERNAME')]) {
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.51.100 -pw ${SSH_PASSPHRASE} "cd /var/www/WebCoreTest && docker build --no-cache -t WebCoreTest_image_dev ."
"""
}
}
}
// 7. 重新建立容器
stage('ReConstruct Container') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: "${params.DEV_TESTSITE_CREDENTIALS}", keyFileVariable: 'SSH_PRIVATE_KEY', passphraseVariable: 'SSH_PASSPHRASE', usernameVariable: 'SSH_USERNAME')]) {
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.51.100 -pw ${SSH_PASSPHRASE} "sudo docker stop WebCoreTest_web_dev && docker rm WebCoreTest_web_dev || true"
"""
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.51.100 -pw ${SSH_PASSPHRASE} "docker run -e ASPNETCORE_ENVIRONMENT=${params.ENVIROMENT} -e LD_LIBRARY_PATH=/app --name WebCoreTest_web_dev -d -p 8065:8080 -p 8066:8081 -v --mount type=bind,source=/var/dockervolumes/WebCoreTest/appsettings.json,target=/app/appsettings.json --mount type=bind,source=/var/dockervolumes/WebCoreTest/appsettings.Development.json,target=/app/appsettings.Development.json WebCoreTest_dev:/app WebCoreTest_image_dev"
"""
}
}
}
// 8. 刪除未使用的 Image
stage('Image Purne') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: "${params.DEV_TESTSITE_CREDENTIALS}", keyFileVariable: 'SSH_PRIVATE_KEY', passphraseVariable: 'SSH_PASSPHRASE', usernameVariable: 'SSH_USERNAME')]) {
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.1.100 -pw ${SSH_PASSPHRASE} "docker image prune -f"
"""
}
}
}
}
}
這部分主要是從 Gitlab 拉取代碼到 Jenkins Server 上
// 1. 從 Gitlab 上 Pull 代碼
stage('Checkout') {
steps {
withCredentials([usernamePassword(credentialsId: "${params.GIT_CREDENTIALS}", passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
checkout([$class: 'GitSCM', branches: [[name: 'remotes/origin/main']], userRemoteConfigs: [[url: 'http://{你的Git網站}/testweb.git']]])
bat """
git pull origin main
"""
bat """
git checkout ${params.GIT_HASH_TAG}
"""
}
}
}
這個範例是 Asp.net Core Web 專案,因此先用 Paht 指向 dotnet.exe
然後產生的發布包放在 Src/publish/WebCoreTest 路徑下
// 2. 從 Jenkins 建置代碼
stage('Building') {
steps {
script {
bat """
path C:/Program Files/dotnet/
dotnet publish Src/WebCoreTest.csproj -c Release -o Src/publish/WebCoreTest
"""
}
}
}
將所有的發布包內容部署到遠端 Linux 的目錄 dockerbuildimage\WebCoreTest\publish
放在此資料夾下的目的是自行建立 Image ,安全性考量,避免直接將 Image Push到 DockerHub 上
// 3. 將建置後的發布包部署到 Linux 機器上
stage('Publish') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: '192.168.1.100(LinuxSite)', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'dockerbuildimage\\WebCoreTes\\publish', remoteDirectorySDF: false, removePrefix: 'Src\\publish\\WebCoreTest', sourceFiles: 'Src\\publish\\WebCoreTest\\**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
由於 Source Code 已經有 Dockerfile 因此直接更新到 遠端 Linux 的目錄 dockerbuildimage\WebCoreTest
// 4. 將DockerFile 檔案複製到 Linux 機器上
stage('Publish DockerFile') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: '192.168.1.100(LinuxSite)', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'dockerbuildimage\\WebCoreTest', remoteDirectorySDF: false, removePrefix: 'Src\\WebCoreTest', sourceFiles: 'Src\\WebCoreTest\\Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
測試連線,確保遠端機器是可用狀態
// 5. (可跳過) 驗證遠端機器是否存活,並且確認 Putty 可用
stage('Connect') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: "${params.DEV_TESTSITE_CREDENTIALS}", keyFileVariable: 'SSH_PRIVATE_KEY', passphraseVariable: 'SSH_PASSPHRASE', usernameVariable: 'SSH_USERNAME')]) {
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.51.100 -pw ${SSH_PASSPHRASE} "echo Connected to 192.168.1.100 server"
"""
}
}
}
在遠端 Linux 機器上建立 Image 檔案
其中以下的語法,會每次重新建立一個 Image
cd /var/www/WebCoreTest && docker build --no-cache -t
PipeLine Stage :
// 6. 建立 Docker Image ,並且存放於遠端機器上
stage('Build Image') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: "${params.DEV_TESTSITE_CREDENTIALS}", keyFileVariable: 'SSH_PRIVATE_KEY', passphraseVariable: 'SSH_PASSPHRASE', usernameVariable: 'SSH_USERNAME')]) {
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.51.100 -pw ${SSH_PASSPHRASE} "cd /var/www/WebCoreTest && docker build --no-cache -t WebCoreTest_image_dev ."
"""
}
}
}
依序執行 刪除舊的容器
-> 建立新的容器
以下幾個是較重要的參數設定:
WebCoreTest_image_dev:latest | latest 會抓最新建立的 Image |
-e LD_LIBRARY_PATH=/app | Linux 系統中共享庫(Shared Libraries)的搜索路徑,強制要求從 /app 開始 |
–mount type=bind,source=/var/dockervolumes/webcoretest/ | |
appsettings.json,target=/app/appsettings.json | Asp.net Core 的設定檔案 |
–mount type=bind,source=/var/dockervolumes/webcoretest/ | |
appsettings.Development.json,target=/app/appsettings.Development.json | Dev 的設定檔案 |
// 7. 重新建立容器
stage('ReConstruct Container') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: "${params.DEV_TESTSITE_CREDENTIALS}", keyFileVariable: 'SSH_PRIVATE_KEY', passphraseVariable: 'SSH_PASSPHRASE', usernameVariable: 'SSH_USERNAME')]) {
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.51.100 -pw ${SSH_PASSPHRASE} "sudo docker stop WebCoreTest_web_dev && docker rm WebCoreTest_web_dev || true"
"""
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.51.100 -pw ${SSH_PASSPHRASE} "docker run -e ASPNETCORE_ENVIRONMENT=${params.ENVIROMENT} -e LD_LIBRARY_PATH=/app --name WebCoreTest_web_dev -d -p 8065:8080 -p 8066:8081 -v --mount type=bind,source=/var/dockervolumes/WebCoreTest/appsettings.json,target=/app/appsettings.json --mount type=bind,source=/var/dockervolumes/WebCoreTest/appsettings.Development.json,target=/app/appsettings.Development.json WebCoreTest_dev:/app WebCoreTest_image_dev"
"""
}
}
}
清空過時的 Image,新的容器會使用新產生的 Image,因此舊的可以刪除
stage('Image Purne') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: "${params.DEV_TESTSITE_CREDENTIALS}", keyFileVariable: 'SSH_PRIVATE_KEY', passphraseVariable: 'SSH_PASSPHRASE', usernameVariable: 'SSH_USERNAME')]) {
bat """
"C:\\Program Files\\PuTTY\\plink.exe" -ssh ${SSH_USERNAME}@192.168.1.100 -pw ${SSH_PASSPHRASE} "docker image prune -f"
"""
}
}
}
建置後如果都成功,每個 Stage 應該都是正常的
在建立 Image 時,會將發布包放在遠端機器上
Json 設定檔案必須部署在 /var/dockervolumes/WebCoreTest/ 路徑下
整個 Contaniner 才能正常執行
這個樣做的好處是更新程式時不影響在 Develop 的配置
輸入遠端機器網址列 假設放在 192.168.100.1
自此完成自動化部署
http://192.168.100.1:8065