2017 年 4 月

第 32 卷,第 4 期

本文章是由機器翻譯。

容器 - 使用 Docker 讓傳統 .NET 應用程式煥然一新

Elton Stoneman

Microsoft.NET Framework 15 年來,舊版的 Framework 版本和舊版的 Windows Server 上執行的無數業務關鍵應用程式已成功執行應用程式平台。這些傳統的應用程式仍然可以提供絕佳的商業價值,但它們可能會很難維護、 升級、 擴充和管理。同樣地,它們可能不足以構成完整重寫所需的投資。使用 Docker,輕量級容器和 Windows Server 2016,在執行應用程式的平台您可以授與傳統應用程式中新的租用壽命 — 加入功能、 增加安全性和效能,並邁向連續部署 — 而不需要冗長且昂貴的重建專案。

在本文中我以連接到 SQL Server 資料庫,一個龐大,因此 ASP.NET WebForms 應用程式,現代化藉由運用 Docker 平台。首先我要移動整個應用程式,而不需要變更任何程式碼,為 Docker,以及輕量型的容器中執行的網站和資料庫。然後我會說明來擴充應用程式、 改善效能,並讓使用者進行自助式分析功能導向的方法。Docker 平台,您會看到如何重複使用的應用程式的新版本、 升級的元件,快速且安全,以及完整的方案部署至 Microsoft Azure。

Docker.NET 解決方案中的什麼位置

Docker 是用於伺服器應用程式 — 網站、 Api、 傳訊解決方案和其他元件在背景中執行。您無法在 Docker 中執行桌面應用程式,因為 Docker 平台和 Windows 主機之間沒有 UI 整合。Out (雖然您可以使用 Docker 來封裝及散發這些桌面應用程式),在容器中執行 Windows Form 或 Windows Presentation Foundation (WPF) 應用程式的規則,但 Windows Communication Foundation (WCF)、.NET 主控台應用程式和 ASP.NET 的所有層面都的最佳候選對象。

若要封裝在 Docker 中執行的應用程式,您可以撰寫小型指令碼呼叫 Dockerfile 自動化部署應用程式的所有步驟。這通常包括 Windows PowerShell 命令設定和指示,複製應用程式內容,並設定任何相依性。您可以解壓縮壓縮的封存或安裝 Msi,,但封裝程序全都自動化完成,因此您無法執行安裝程序擁有 Windows UI 和需要使用者的輸入。

當您在查看方案架構,找出哪些部分可以在 Docker 容器中執行,請記得任何元件,可以安裝並執行,而 Windows UI 不是很好的候選。本文著重於.NET Framework 應用程式,但您可以在 Windows 伺服器,包括.NET Core、 Java、 Node.js 及到應用程式執行的 Windows 容器內執行的任何項目。

移轉至容器的.NET 應用程式

您移轉至 Docker 的方式取決於目前執行您的應用程式如何。如果您在 HYPER-V 虛擬機器中執行的完整設定應用程式,開放原始碼 Image2Docker 工具可以自動產生 Dockerfile 從 VM 的磁碟。如果您有發行 MSI 或 WebDeploy 套件建置程序時,很容易撰寫您自己 Dockerfile Docker 中樞上使用其中一個 Microsoft 的基底映像。

以下是指令碼到 Docker 映像 ASP.NET WebForms 應用程式在封裝完成 Dockerfile:

FROM microsoft/aspnet:windowsservercore-10.0.14393.693
SHELL ["powershell"]
RUN Remove-Website -Name 'Default Web Site'; \
    New-Item -Path 'C:\web-app' -Type Directory; \
    New-Website -Name 'web-app' -PhysicalPath 'C:\web-app' -Port 80 -Force
EXPOSE 80
RUN Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' \
    -Name ServerPriorityTimeLimit -Value 0 -Type DWord
COPY ProductLaunch.Web /web-app

有我所需的九個行指令碼並沒有應用程式的變更。這可能是目前在 Windows Server 2003 上執行的 ASP.NET 2.0 應用程式 — 使用此 Dockerfile 我可以建置立即升級到 Windows Server 2016 和.NET Framework 4.5 的應用程式的映像。我會一一介紹這些指示︰

  • 從 microsoft/aspnet 告訴 Docker 来做為起點的映像。在此情況下,它是 IIS 和 ASP.NET 安裝在特定版本的 Windows Server Core 之上的 Microsoft 映像。
  • 讓我可以執行 PowerShell 指令程式不同的殼層 Dockerfile 的其餘部分變更殼層 ["powershell"]。
  • 執行的移除網站會使用 PowerShell 來設定 IIS,移除預設的網站,並建立一個新的應用程式的已知位置。
  • 公開 80 開啟通訊埠 80 明確加入至容器允許網路流量,因為 Docker 容器已鎖定的預設值。
  • 執行 Set-itemproperty 會關閉 Windows DNS 快取內的映像,因此任何 DNS 要求都由提供服務 Docker。
  • 主機上的 ProductLaunch.Web 目錄 ProductLaunch.Webcopies 已發佈的網站專案複製到映像。

Dockerfile 類似 Web 應用程式的部署指南,但而不是模糊的人為文件,它是精確且可採取動作的指令碼。產生封裝的應用程式執行 docker 建置包含 Dockerfile 和已發佈的網站目錄中的命令︰

docker build --tag sixeyed/msdn-web-app:v1 .

此命令會建立具有名稱 sixeyed/msdn web 的應用程式以及標記 v1 的 Docker 映像。名稱為中心 (sixeyed),包含我的使用者帳戶,因此我可以共用此映像我的認證登入,並將它推送到中心。因此當我封裝應用程式的新版本時,映像名稱會保持不變,但是會 v2,標記可用於版本控制影像。

現在我可以從映像執行容器,將會啟動應用程式,而範例應用程式會相依於 SQL Server,我需要 SQL Server 執行我才能啟動網站。

從 Docker 中樞提取相依性

Docker 具備網路堆疊,可讓容器透過虛擬網路,連線彼此,也可讓連線到外部主機實體網路上執行的容器。如果我在網路的機器上執行的 SQL Server 執行個體,容器中的 ASP.NET 應用程式可以使用它,我只需要在連接字串中指定的伺服器名稱。我可以在容器中,執行 SQL Server 或 Web 應用程式都能夠存取連接字串中使用的容器名稱。

SQL Server Express 是由 Microsoft 維護的映像中可用 Docker 中樞上。若要啟動資料庫容器,該映像,執行︰

docker run --detach `
 --publish 1433:1433 `
 --env sa_password=MSDNm4g4z!n3 `
 --env ACCEPT_EULA=Y `
 --name sql-server `
 microsoft/mssql-server-windows-express

這會在背景以卸離旗標啟動容器,以及發佈連接埠 1433,因此我可以連接到外部,從容器中的 SQL 執行個體可能在主機上使用 SQL Server Management Studio。Env 選項是索引鍵 / 值組,容器內之 Docker 介面與系統環境變數。若要確認已接受授權合約,並且設定 sa 使用者的密碼,SQL Server 映像會使用這些值。

若要執行的容器,Docker 必須在本機上有一份映像。發佈已內建 Docker 平台,因此如果您沒有 SQL Server Express 的映像在本機當您執行此命令,而 Docker 將會下載從中樞。有一半以上 1 百萬個映像在 Docker 中樞內,已經下載超過 9 無數次。Docker 啟動 Linux 世界中,和大部分的這些映像未 Linux 應用程式,但有越來越多的高品質 Windows 應用程式可以下載並直接進入您的方案卸除。

現在,SQL Server 執行 Docker 容器中,我的 Web 應用程式會使用連接字串中的主機名稱為 sql server,將會連接到在 Docker 中執行的資料庫。我可以在背景啟動 WebForms 應用程式,並發佈連接埠 80,讓網站存取︰

docker run --detach `
 --publish 80:80 `
 sixeyed/msdn-web-app:v1

如果外部的電腦上連接埠 80 傳送要求到我的主機,Docker 接收要求,並以透明方式將它轉送到容器中執行的 ASP.NET 應用程式。如果我在處理主應用程式,需要使用 「 檢查 docker 」 取得容器的 IP 位址,瀏覽至容器,以查看站台,也就是簡單的產品啟動 microsite。您可以看到資料擷取頁面從站台執行中的 Docker [圖 1

在 Docker 中執行的網站註冊頁面
在 Docker 中執行的網站的 [圖 1] 註冊畫面

執行 「 docker ps 」,您會看到一份所有正在執行的容器。資料庫有一個 Web 應用程式,而且您同時管理相同的方式 — 「 docker 上層 」 會顯示在容器中,執行程序「 docker 記錄 」 顯示您在記錄檔輸出從應用程式。和 「 docker 檢查 」 會顯示您已開啟哪些連接埠和主機的其他容器的相關資訊。一致性是 Docker 平台的主要好處。應用程式封裝、 發佈和管理方式相同,無論他們使用何種技術。

將分割從整合應用程式的功能

現在,應用程式現代化的平台上執行,我可以啟動現代化應用程式本身。整合型的應用程式分成較小的服務可以顯著專案的工作,但可以透過對等的定期變更,使您可以將更新部署至已變更的功能不含迴歸測試整個應用程式的主要功能採用目標更明確的方式。非功能性需求而不需要完整重新架構的應用程式受惠於另一種設計的功能也可以是很好的選擇。

我要先介紹修正效能問題。在現有的程式碼中,應用程式會讓同步連線到資料庫來儲存使用者資料。方法不好調整 — 大量並行使用者會使 SQL Server 的瓶頸。與訊息佇列的非同步通訊是骨子裡更具彈性的設計。這項功能,我可以發佈至訊息佇列從 Web 應用程式事件,並將資料持續性程式碼移到可處理該事件訊息的新元件。

這種設計並未妥善調整。如果我有的網站,我可以執行更多容器以處理增加的連入要求的多個主機的流量突然增加。事件訊息會保留在佇列中,直到取用的訊息處理常式。沒有特定 SLA 的功能,您可以有一個執行單一容器中的訊息處理常式,並依賴的所有事件將會取得最後都處理的訊息佇列的保證。SLA 導向功能可以擴充執行更多的訊息處理常式容器保存層。

本文所附的原始程式碼已經有第 1 版、 第 2 版和第 3 版的應用程式的資料夾。在第 2 版,SignUp.aspx 頁面會發行當使用者提交的詳細資料表單事件︰

var eventMessage = new ProspectSignedUpEvent
{
  Prospect = prospect,
  SignedUpAt = DateTime.UtcNow
};
MessageQueue.Publish(eventMessage);

也在第 2 版沒有共用的傳訊專案,以區隔的訊息佇列和接聽 Web 應用程式所發行的事件,並將使用者的資料儲存到資料庫的主控台應用程式的詳細資料。在主控台應用程式中的持續性程式碼直接提昇從第 1 版中的程式碼的 Web 應用程式,以便實作相同但已現代化功能的設計。

新版的應用程式有許多的工作部分,分散式的解決方案中所示**[圖 2**。

現代化的應用程式有許多使用組件
[圖 2 現代化的應用程式有許多使用組件

元件之間有相依性,而且它們需要啟動正確的順序,方案才能正常運作。這是協調跨許多容器中執行的應用程式的問題之一,但 Docker 平台的分散式應用程式視為第一等公民應付的。

使用 Docker 協調應用程式撰寫

Docker Compose 是著重於分散式應用程式的 Docker 平台的一部分。您可以定義您的應用程式的所有組件簡單的文字檔案,包括它們與任何所需的組態值之間的相依性服務的身分。這是 Docker Compose 第 2 版,顯示的 Web 應用程式組態檔的一部分︰

product-launch-web:
  image: sixeyed/msdn-web-app:v2
  ports:
    - "80:80"
  depends_on:
    - sql-server
    - message-queue
  networks:
    - app-net

在這裡,我已經指定要用於 [我的 Web 應用程式的映像的版本。發佈連接埠 80,然後我明確地陳述,Web 應用程式而定的 SQL Server 和訊息佇列的容器。若要存取這些容器,Web 容器必須能夠在相同的虛擬 Docker 網路,讓 Docker Compose 檔案中的所有容器都加入相同的虛擬網路,稱為應用程式網路。

其他地方 Docker Compose 檔案中定義的 SQL Server,在 Docker 中樞內,使用 Microsoft 映像服務與我使用 NAT 傳訊系統,我是高效能開放原始碼的訊息佇列的訊息佇列服務。NAT 是官方 Docker 中樞映像。最後一個服務的訊息處理常式,這是.NET 主控台應用程式封裝做為 Docker 映像,使用簡單 Dockerfile。

現在我可以執行應用程式使用 Docker Compose 命令列︰

docker-compose up -d

再 Docker Compose 啟動容器的每個元件中正確的順序,能夠讓我從單一命令的有效的解決方案。Docker 映像和 Docker Compose 檔案存取權的任何人都可以執行應用程式,且它可運作的方式 — 在 Windows 10 的膝上型電腦,或資料中心內執行的 Windows Server 2016 機器或在 Azure 上。

為了讓第 2 版,我對小幅變更從一個元件的功能實作移至另一個應用程式程式碼。使用者行為是相同的但方案現在是易於擴充,因為 Web 層就可以分隔資料層,而訊息佇列會處理任何流量暴增情況。新的設計,很容易擴充,,,我將介紹事件驅動的架構,因此我可以觸發新的行為插入現有的事件訊息。

新增進行自助式分析

我的範例應用程式,我變更一次多個要顯示多少您可以使用 Docker 平台,非常不費吹灰之力。應用程式目前使用 SQL Server 做為交易式的資料庫,以及我要加入的第二個資料存放區做為報告資料庫。這可以讓我保留報告交易的考量,從不同的考量,而且也讓我的技術堆疊的任意選擇。

在範例程式碼的第 3 版,我新增了新的.NET 主控台應用程式接聽相同事件的訊息發佈的 Web 應用程式。當兩個主控台應用程式執行時,NAT 訊息佇列可確保它們都獲得一份所有事件。新的主控台應用程式接收事件,並將使用者資料儲存在 Elasticsearch,您可以執行 Windows Docker 容器中的開放原始碼文件存放區。Elasticsearch 是不錯的選擇,因為它靈活,所以我可以在多個容器,重複,叢集化,而且因為它有絕佳使用者端前端提供稱為 Kibana。

我還沒有進行任何變更的 Web 應用程式或 SQL Server 訊息處理常式從第 2 版,Docker Compose 檔案中,我只是加入新的服務,Elasticsearch 和 Kibana,因此新的訊息處理常式,會將文件寫入 Elasticsearch 索引︰

index-prospect-handler:
  image: sixeyed/msdn-index-handler:v3
  depends_on:
    - elasticsearch
    - message-queue
  networks:
    - app-net

Docker 撰寫應用程式,可以進行累加式升級,它將不會取代執行容器,如果其定義符合 Docker Compose 檔案中的服務。在範例應用程式的第 3 版,有新的服務,但不服務至現有的任何變更,因此當我執行 docker-撰寫出 – d、 Docker 將會執行新的容器 Elasticsearch、 Kibana 和索引的訊息處理常式,但保留其他當做執行 — 這對非常安全的升級程序,您可以新增功能,而不用讓應用程式離線。

因此像 Elasticsearch 它們設定為在應用程式,預設值,只需要確定的相依性的主機名稱的容器名稱符合 Docker Compose 的安裝程式中,此應用程式的慣用慣例組態。

當啟動新的容器時,我可以使用 「 檢查 docker 」 以取得 Kibana 容器的 IP 位址,並瀏覽至該位址的連接埠 5601。Kibana 有一個非常簡單的介面,並在幾分鐘的時間,我可以建置顯示關鍵計量人士及其詳細資料,註冊中所示的儀表板**[圖 3**。

Kibana 儀表板
圖 3 Kibana 儀表板

進階使用者很快就會發現自己的方向 Kibana,而他們將能夠做出自己的視覺效果和儀表板,而不需要洽詢 IT。而不需要停機我新增了自助式分析應用程式。這項功能的核心是來自我至我的解決方案取自 Docker 中樞的企業級開放原始碼軟體。資料送入文件存放區的自訂元件是簡單.NET 主控台應用程式,大約 100 行程式碼。Docker 平台程式碼一起插入元件。

執行 Dockerized 解決方案在 Azure 上

Docker 的另一大優點是方便攜帶。應用程式封裝至 Docker 映像在任何主機上執行相同的方式。本文最後的應用程式會使用 Microsoft; 所擁有的 Windows Server 和 SQL Server 映像curated Docker; 由 NAT 映像和我自己的自訂映像。所有這些映像已發行 Docker 中樞,讓任何 Windows 10 或 Windows Server 2016 電腦可以提取映像,並從這些執行容器。

現在我的應用程式已準備好進行測試,並將它部署至 Azure 上的共用環境很簡單。我已在 Azure 中使用 Windows Server 2016 Datacenter 容器] 選項建立虛擬機器 (VM)。VM 映像隨附 Docker 安裝和設定,並下載 Windows Server Core 和 Nano 伺服器的基底 Docker 映像。不包含在 VM 中的一個項目是 Docker Compose,我從 GitHub 發行頁面下載。

全都放在公用儲存機制上 Docker 中樞是 Docker Compose 檔案中所用的影像。私用軟體堆疊,您不想公開可用所有映像。您仍然可以使用 Docker 中樞並將映像保留在私用儲存機制,或者您可以使用替代的裝載的登錄,像是 Azure 容器登錄。您自己的資料中心內您可以使用內部部署選項,例如 Docker 信任登錄。

我的映像是公用的因為我只需要複製到 Azure VM 的 Docker Compose 檔案,並執行 docker-撰寫出 – d。Docker 會提取所有映像從中樞,並從它們的容器執行正確的順序。每個元件使用慣例來存取其他元件,以及這些慣例內建 Docker Compose 上的檔案,所以即使完全全新的環境,解決方案就可以啟動並如預期般執行。

如果您所處理的企業軟體版本,其中設定新的環境是手動、 風險和緩慢的程序,您會看到多少的好處是可以從 Windows Server 2016 和 Docker 平台將十分可觀。Docker 方案中的索引鍵成品 — Dockerfile 和 Docker Compose 檔案 — 會簡單、 模稜兩可取代手動部署文件。它們鼓勵自動化和它們輕鬆地建置、 出貨和任何一部電腦上有一致的方式執行方案。

後續步驟

如果您很希望能夠自行嘗試 Docker,Image2Docker PowerShell 模組是好的開始。可讓您建置 Dockerfile 並協助您快速學習程序。上有一些很棒、 自修課程training.docker.com,這會為您的環境。然後,當您準備繼續時,簽出 Docker 實驗室於 GitHub,有許多 Windows 容器逐步解說。

您可以聽聽 Docker 的所有層面的從業人員和專家討論的世界各地也有 Docker 所在地。大 Docker 會議是 DockerCon,總是 sell-out;今年執行於德州年 4 月和哥本哈根 10 月。最後,請參閱 Docker Captains — 它們 Docker 相當於 Microsoft Mvp。他們經常部落格,請透過推特,講述所有酷炫的內容進行使用 Docker,並遵循它們是保留 pulse 技術的好方法。


Elton Stoneman是七次 Microsoft MVP 和 Pluralsight 作者在 Docker 擔任開發人員擁護者。 他有架構及自 2000年交付成功的解決方案,與 Microsoft 技術、 最新 API 和巨量資料專案 Azure,並使用 Docker 的分散式應用程式。

由於這篇文章者以下技術專家︰ Mark 健全狀況
Mark 健全狀況是專精於 Azure、 NAudio,建立者和作者 pluralsight 的.NET 開發人員。在他的部落格markheath.net ,您可以關注他的 Twitter: @mark_heath