
在 DevOps 的實踐中,自動化部署是提升交付效率的關鍵一環。當我們的 CI 流程已經能自動打包出 Docker 映像並推送到私有倉庫後,下一步就是讓目標伺服器自動拉取映像並啟動服務。這篇文章我會分享如何撰寫一套完整的部署腳本,並將它整合進 Jenkins 的建置流程中。
自動部署的核心流程
整個自動部署的邏輯大致可以拆分成以下幾個步驟:
| 步驟 | 說明 |
|---|---|
| 1 | 通知目標伺服器要拉取哪個映像 |
| 2 | 檢查伺服器上是否有正在運行的同名容器,若有則停止並移除 |
| 3 | 檢查伺服器上是否已存在同版本的舊映像,若有則刪除 |
| 4 | 從私有映像倉庫(如 Harbor)拉取指定版本的映像 |
| 5 | 將拉取的映像啟動成容器並對外提供服務 |
一、在目標伺服器上準備部署腳本
1.1 停止並刪除舊容器
首先,我們需要判斷目標伺服器上是否已有同名容器在運行。透過以下指令可以取得容器 ID:
docker ps -a | grep ${project} | awk '{print $1}'
如果有回傳容器 ID,代表容器正在運行或已停止但仍存在。此時我們需要先停止再刪除:
containerId=$(docker ps -a | grep ${project} | awk '{print $1}')
if [ "$containerId" != "" ]; then
docker stop $containerId
docker rm $containerId
fi
1.2 刪除舊版映像
接著檢查是否有同名的舊版映像存在。要注意的是,同一個專案可能會有多個 tag 的映像,所以判斷邏輯稍有不同:
tag=$(docker images | grep ${project} | awk '{print $2}')
if [[ "$tag" =~ "$version" ]]; then
docker rmi $imageName
fi
1.3 登入倉庫並拉取映像
接下來登入私有倉庫(以 Harbor 為例),然後拉取映像:
docker login -u ******** -p ******** $harbor_addr
docker pull $imageName
1.4 完整的部署腳本
把上面的片段組合起來,就是一份完整的 deploy.sh:
#!/bin/bash
set -euo pipefail
# 使用方式:./deploy.sh <harbor位址> <倉庫名稱> <專案名稱> <版本號> <宿主機埠> <容器埠>
harborAddr=$1
harborRepo=$2
project=$3
version=$4
hostPort=$5
containerPort=$6
imageName=$harborAddr/$harborRepo/$project:$version
echo "目前映像資訊:$imageName"
# 停止並刪除舊容器
containerId=$(docker ps -a | grep ${project} | awk '{print $1}')
if [ "$containerId" != "" ]; then
echo "停止並刪除舊容器:$containerId ..."
docker stop $containerId
docker rm $containerId
echo "容器刪除完成。"
fi
# 刪除舊版映像
tag=$(docker images | grep ${project} | awk '{print $2}')
if [[ "$tag" =~ "$version" ]]; then
echo "刪除舊版映像:$version ..."
docker rmi $imageName
echo "映像刪除完成。"
fi
# 登入 Harbor
docker login -u ******** -p ******** $harborAddr
# 拉取映像
echo "開始拉取映像:$imageName ..."
docker pull $imageName
echo "映像拉取完成。"
# 啟動容器
echo "開始部署映像 ..."
docker run -d -p $hostPort:$containerPort --name $project $imageName
echo "部署成功!"
記得賦予腳本執行權限:
chmod a+x deploy.sh
測試一下腳本是否能正常運作:
./deploy.sh 192.168.x.x:80 repo my-project v3.0.0 8081 8080
執行後你應該會看到容器被正確啟動,透過 docker ps 可以確認映像已經部署完成。

二、在 Jenkins 中整合部署流程
2.1 將腳本放到 PATH 路徑下
為了讓腳本可以在任何地方被呼叫,我們把它移動到系統的 PATH 路徑下:
mv deploy.sh /usr/bin/
這樣不管在哪個目錄,都可以直接執行 deploy.sh。
2.2 在 Jenkins 設定建置參數
在 Jenkins 的任務設定中,新增以下參數化建置的欄位:
| 參數名稱 | 類型 | 說明 |
|---|---|---|
project | 字串參數 | 專案名稱 |
hostPort | 字串參數 | 宿主機對外的埠號 |
containerPort | 字串參數 | 容器內部的埠號 |
2.3 設定建置後操作
在建置後操作區塊,選擇 Send build artifacts over SSH,並在 Exec command 欄位中填入:
deploy.sh 192.168.x.x:80 repo $project $tag $hostPort $containerPort
這行指令會在遠端伺服器上自動執行部署腳本,參數由 Jenkins 的建置參數自動帶入。儲存設定後就大功告成了。
三、執行建置並驗證部署
最後,點擊 Jenkins 的「Build with Parameters」按鈕,填入對應的參數值後觸發建置。整個流程會自動完成:
- 程式碼編譯與打包
- Docker 映像建置與推送到 Harbor
- 透過 SSH 在目標伺服器上執行部署腳本
- 舊容器清理、新映像拉取、容器啟動
建置完成後,瀏覽目標服務的位址即可看到最新版本已經上線。
小結
這套自動化部署腳本雖然不複雜,但它涵蓋了實際部署中常見的場景處理——容器清理、映像管理、自動拉取與啟動。搭配 Jenkins 的參數化建置與 SSH 發佈功能,我們就能實現從程式碼提交到服務上線的一條龍自動化流程。後續如果要進階,還可以考慮加入健康檢查、滾動更新或搭配 Kubernetes 來做更精細的容器編排。

發佈留言