前言
在 上一篇 介紹了使用 Azure 的 Web App For Container 服務將 Docker Image 部署至 Microsoft Azure,在 Demo 過程中 Image 是放置在公開的 Docker Hub 上,但在實務上不太可能將應用程式 Docker Image 檔案公開,如果希望可以建立私有的 Docker 服務時可以使用 Azure 中的 Container Registry 服務,建立個人/公司專用的私人 Docker 上傳空間,這篇文章就來簡單介紹建立 Azure Container Registry 服務的步驟與操作,以及上傳完成之後發送通知給 Microsoft Teams 頻道的團隊成員,若有問題或是錯誤的地方歡迎各方高手大大一起討論或給予指導。
前置作業
在開始前需先檢查電腦中是否有安裝下列軟體,才可以順利進行後續的步驟
安裝 Microsoft Teams
Teams 是微軟在 2018 年 7 月所推出的團隊協作平台,整合 Office 365、Skype 以及 Outlook 等功能,方便團隊在線上進行溝通的工作,有提供免費版本支援 40 種語系讓有需要的企業使用,更多詳細資訊可以參考 Teams 官方介紹。在此我們的應用情境是當有人上傳 Docker image 到 Azure Container Registry 時候會主動發送通知到 Teams 的頻道中,讓團隊的成員收到上傳 image 成功的消息。
安裝 Docker For Windows
在 Windows 作業系統要操作 Docker 那麼 Docker for windows 是不可或缺的工具,安裝 Docker 與操作細節可以參考小弟之前寫的 Docker for windows 初體驗 文章介紹,安裝傳送門 : Docker Desktop for Windows
建立 Container Registry
首先第一步是要先建立 Azure Container Registry,建立方式先到 Azure Portal 首頁選擇左上方建立資源 > 容器 > Container Registry
建立新的 Container Registry 需要輸入以下資訊
登錄名稱 : 名稱輸入 dockerregistrylab
資源群組 : 可以選擇建立新的資源群組
位置 : 這裡選擇亞洲日本西部
SKU : 與計價有關,一開始如果沒特別需求先選擇基本
按下建立之後,很快的完成建立新的 Container Registry 的動作,在完成頁面可以看到稍早所設定的資訊像是群組、位置、伺服器與 SKU 等設定內容,這裡我們先將登入伺服器內容複製起來稍後測試上傳時會用到
Docker Image上傳測試
建立完 Container Registry 之後為了確保是可以使用的,因此我們進行簡單的上傳 Docker image 測試,首先使用 admin 開啟 powershell 視窗
首先要登入 Azure Container Registry,在稍早開啟的 powershell 中輸入 az acr login + 伺服器名稱 來進行登入的動作
az acr login --name dockerregistrylab
回傳 Login Success 代表已登入成功,稍早提到要針對新增的 Container Registry 進行測試,因此我們可以下載 hello-world 的 Docker Image 檔在上傳到新增的 Azure Docker Server 上,先透過 docker pull 指令取得 image 檔案
PS C:\Users\username> docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
Digest: sha256:451ce787d12369c5df2a32c85e5a03d52cbcef6eb3586dd03075f3034f10adcd
Status: Image is up to date for hello-world:latest
docker.io/library/hello-world:latest
接著在 image 上透過 docker tag 指令加上 tag,在將 image 檔案透過 docker push + 伺服器位置 指令將 Docker image 上傳到 dockerregistrylab 上面,其中要注意的伺服器是要輸入位置而不僅僅是名稱,在此範例中伺服器位置要輸入的值是 dockerregistry.azurecr.io ,指令操作過程如下
PS C:\Users\username> docker tag hello-world dockerregistrylab.azurecr.io/helloworld:v1
PS C:\Users\username> docker push dockerregistrylab.azurecr.io/helloworld:v1
The push refers to repository [dockerregistrylab.azurecr.io/helloworld]
af0b15c8625b: Pushed
v1: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524 PS C:\Users\marcustung> docker pull hello-world Using default tag: latest latest: Pulling from library/hello-world Digest: sha256:451ce787d12369c5df2a32c85e5a03d52cbcef6eb3586dd03075f3034f10adcd Status: Image is up to date for hello-world:latest docker.io/library/hello-world:latest
PS C:\Users\username>
上傳完畢之後可以到 Azure Portal 介面確認上傳的檔案,可以到操作介面的左邊點選 存放庫 進行確認,可以看到稍早上傳的 helloworld Docker image 已上傳成功
透過以上簡單的步驟,就可以在 Azure 上建立屬於自己的 Container Registry。
整合 Teams
一開始有提到另外一個代辦事項是當上傳 Docker image 後要發送訊息到 Teams 的頻道,告知團隊成員 image 檔案的狀態資訊,接下來在整合 Teams 發送通知將會分為以下幾個步驟
Teams 頻道 : 建立負責接收 ACR 訊息通知的頻道
Azure Function : 當上傳成功時,接收 ACR Webhook 訊息處理後轉發給 Teams
ACR Webhook : 負責發送 ACR 通知的服務
Teams 頻道
首先在 Teams 中建立一個名字叫 ACR Version Notifier 的通知頻道,建立後在頻道按右鍵選擇 連接器
連接器部分預設會以人氣指數進行排序,我們這次要接的服務是 Webhook
接下來會需要定義 incoming webhook 連接器的名字,在此輸入 ACR webhook ,並按下下方的建立按鈕
在建立完成之後會有屬於此連接器的 url 位置,這是 Teams incoming webhook 負責接收訊息的 URL,這裡要複製下來等等在 Azure function 會用到
Azure Function
接下來動作是要建立 Azure function 服務,主要工作內容是當上傳 Docker Image 成功時,接收 ACR Webhook 所發出來的訊息轉發給 Teams,或許你會好奇為什麼不直接用 Teams 來接收 ACR Webhook 發送的通知就好,還要在特別建立 Azure Function 來做處理的動作,自己經過嘗試之後發現 Teams 在接收 incoming 的 json 內容要有 title 與 text 兩個欄位,但在 Azure webhook 發送時並未包含這兩個欄位,因此在串接上會有造成錯誤 Teams API 會回傳不接受訊息,此時可以透過在 Azure Function 上撰寫簡單的 C# 代碼進行轉換即可解決此問題。
建立 Azure function 可以透過很多種方式來建立,這裡使用的是從 Portal 上直接建立,如果想了解其他建立方式可以參考官網說明文件 : 傳送門,在 Azure Portal 左邊 menu 選單點擊 建立資源,應用程式名稱輸入 acrnotifyteams
接著要新增函式,在左邊選單選擇新增函式 > 入口網站 > Webhook + API
建立完畢後可以看到會有新增好的 Httptrigger1 的函式,右邊是要執行的 C# Code 相關功能
先透過簡單的測試來看稍早在 Teams 的連接器是否 work,在一開始有提到 Teams 連接器 API 使用的 json 格式需要有 title & text,因此我先使用 httpclient 發送簡單的測試訊息測試
提醒 : httpclient.PostAsync 網址就是上一步所複製的連接器 Url
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var client = new HttpClient();
var json = "{\"title\": \"Title Test\", \"text\": \"9527 就是你的終身代號\"}";
log.LogInformation(json);
await client.PostAsync("https://outlook.office.com/webhook/yourteamsurl", new StringContent(json, System.Text.Encoding.UTF8, "application/json"));
return (ActionResult)new OkObjectResult($"ok");
}
測試後即可看到 Teams 正常收到所發送的訊息
設定 Webhook
接著回到 Container Registry 頁面,新增 Webhook 並在服務 url 的地方加上稍早建立 Azure function 網址
在根據 webhook 發送的通知 json 內容調整 azure function 如下
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
string repository = data?.target.repository;
string tag = data?.request.tag;
var client = new HttpClient();
var json = "{\"title\": \"Docker Image :" + repository + " pull success\", \"text\": \"" + repository + ":" + tag + "\"}";
log.LogInformation(json);
await client.PostAsync("https://outlook.office.com/webhook/4cbb9e75-0910-41e3-81ec-84a158988cc4@938ecd8f-754e-4e60-883d-bad2b0b26a9e/IncomingWebhook/1ab11e49ab0f4497922cef639d185223/42c59a4e-ea5b-43d8-8edb-21f3572bf85a", new StringContent(json, System.Text.Encoding.UTF8, "application/json"));
return (ActionResult)new OkObjectResult($"ok");
}
測試上傳 Docker Image
在重新上傳一次 docker image,即可看到已成功通知 Teams
格式內容可以再依據需求調整,Docker Image 上傳至 Azure Container Registry 整合 Team 宣告整合成功 :)