← 返回上一頁
CI/CD Docker

透過 Docker 拉取鏡像實現自動化部署:從腳本到 Jenkins 整合

本頁目錄
CI/CD Pipeline 使用 Jenkins、Docker、Harbor 的部署流程架構圖
CI/CD Pipeline 使用 Jenkins、Docker、Harbor 的部署流程架構圖
CI/CD Pipeline 架構:GitHub → Jenkins → Docker Build → Harbor → Deploy

在 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 可以確認映像已經部署完成。

Docker CI/CD Pipeline 自動化部署流程示意圖
Docker 搭配 CI/CD 實現自動化部署流程

二、在 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」按鈕,填入對應的參數值後觸發建置。整個流程會自動完成:

  1. 程式碼編譯與打包
  2. Docker 映像建置與推送到 Harbor
  3. 透過 SSH 在目標伺服器上執行部署腳本
  4. 舊容器清理、新映像拉取、容器啟動

建置完成後,瀏覽目標服務的位址即可看到最新版本已經上線。

小結

這套自動化部署腳本雖然不複雜,但它涵蓋了實際部署中常見的場景處理——容器清理、映像管理、自動拉取與啟動。搭配 Jenkins 的參數化建置與 SSH 發佈功能,我們就能實現從程式碼提交到服務上線的一條龍自動化流程。後續如果要進階,還可以考慮加入健康檢查、滾動更新或搭配 Kubernetes 來做更精細的容器編排。

分享這篇
X LinkedIn Facebook Hacker News Reddit

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料