.NET 6 現在包含在 Ubuntu 22.04 (Jammy) 中,只需 apt install dotnet6
即可安裝。此更改是 Ubuntu 使用者的一項重大改進和簡化。我們還發布了帶有 Chiseled Ubuntu 容器 的 .NET,這是 Canonical 的一個新的小型且安全的容器產品。這些改進是 Canonical 和 Microsoft 之間合作的成果。
以下是在 Ubuntu 22.04 上安裝 .NET 6 SDK 的命令:
sudo apt update
sudo apt install dotnet6
我們還宣佈 .NET 6 可用於 Chiseled Ubuntu 容器。我們在 Canonical 的朋友開發了一種新的chisel方法來製作超小型容器影像。我們對此感到非常高興。Chiseled Ubuntu 影像比您之前使用的 Ubuntu 影像小 100MB
!
下面是拉取新的 ASP.NET Chiseled 影像的命令:
docker pull mcr.microsoft.com/dotnet/nightly/aspnet:6.0-jammy-chiseled
我們還更新了 dotnetapp 和 aspnetapp 示例,以便您可以嘗試使用 Chiseled Ubuntu容器中的 .NET。
- 這些新的容器影像顯著改善了安全態勢:
- 超小影像(減小尺寸和攻擊面)
- 沒有包管理器(避免一整類攻擊)
- 無外殼(避免一整類攻擊)
- 非root(避免一整類攻擊)
最重要的是,Canonical 和 Microsoft 致力於合作以確保新的 .NET 版本與新的 Ubuntu 版本一起很好地協同工作。這包括安全更新和容器影像的安全交付。我們非常高興 .NET 6 在 Ubuntu 22.04 中可用,並且 Canonical 選擇與我們合作作為其 Chiseled Ubuntu 影像的釋出合作伙伴。這就是 Canonical 對該專案所說的。
Canonical 產品經理 Valentin Viennot 說:“Ubuntu 現在擁有從開發端到生產端的故事,從 .NET 平臺開始,支援超小型容器影像。” “我們認為這對我們兩個社群來說都是一個巨大的進步;與 Microsoft 的 .NET 團隊合作使我們能夠超越。
Canonical and Microsoft
幾個月前,Canonical 和 Microsoft開始合作,目標是讓 Ubuntu 成為更好的.NET開發環境。
我們有兩個主要目標:
- 在 Ubuntu 上使用 .NET 進行簡化。
- 縮短 Canonical 和 Microsoft 之間的供應鏈。
多年來,我們都知道許多 .NET 開發人員使用 Ubuntu。在我們交談之後,很明顯我們可以做一些事情來改善這種體驗。讓我告訴您我們交付了什麼。
APT 中的 .NET
您現在可以使用由 Canonical 透過 source-build 構建的 APT 安裝 .NET 6。這些軟體包可用於 Ubuntu 22.04 (Jammy) 及更高版本。這是升級到 Jammy 的一個很好的理由!
注意:現在 .NET 6 已包含在 Ubuntu 中,請檢視我們關於在 Ubuntu 22.04 上使用 packages.microsoft.com 的建議。
有多個包:
- dotnet6 — .NET 6 SDK(簡稱)。
- dotnet-sdk-6.0 — 同上(全稱)。
- aspnet-runtime-6.0 — ASP.NET Core
- dotnet-runtime-6.0 — .NET Runtime
我將向您展示如何使用 Docker 安裝這些影像(相同的模型適用於其他地方):
rich@kamloops:~$ docker run --rm -it ubuntu:jammy
root@7d4dfca0ef55:/# apt update && apt install -y dotnet6
root@7d4dfca0ef55:/# dotnet --version
6.0.108
如果這不起作用,您需要在 /etc/apt/sources.list 中註冊以下源:
deb http://archive.ubuntu.com/ubuntu/ jammy-updates universe
Canonical 和 Microsoft 將合作確保這些軟體包在每月的 .NET 團隊釋出計劃中更新。這包括 Microsoft 在公開發布之前與 Canonical 共享 CVE 資訊(描述和程式碼)。同樣,Canonical 將在另一個方向共享安全資訊。
注意:
- 我們目前缺少 Arm64 版本。這些很快就會到來。兩家公司都是 Arm64 的堅定支持者。
- .NET 7 版本尚不可用,並且可能要等到 .NET 7 GA 之後才會提供。
.NET SDK 工作負載在包中不可用(對於任何 Linux 發行版)。此外,Linux 不支援 .NET MAUI 工作負載。
.NET 在Chiseled Ubuntu 容器中
您現在可以在 Chiseled Ubuntu 容器中使用 .NET。Chiseling 提供最小的容器佔用空間,同時仍然是您瞭解和信任的 Ubuntu。它類似於傳統的 distroless,帶有一個為切片 .deb
包而定製的工具。
這些影像比我們目前提供的 Ubuntu 影像小 100MB
,而且不包括 root 使用者!
我們為 Arm64 和 x64 以及 .NET 6 和 7 提供三層 Chiseled Ubuntu 容器影像:
mcr.microsoft.com/dotnet/nightly/runtime-deps:6.0-jammy-chiseled
mcr.microsoft.com/dotnet/nightly/runtime:6.0-jammy-chiseled
mcr.microsoft.com/dotnet/nightly/aspnet:6.0-Jammy-chiseled
注意:影像將在我們的夜間
儲存庫中提供,而chiseled的產品處於預覽狀態。當它們在生產中得到支援時,我們將釋出另一個公告。這將是今年的某個時候,但我們還沒有選擇一個時間表,因為我們一直專注於基本的啟用。
Canonical 還透過 Docker Hub 釋出適用於 .NET 的 Chiseled Ubuntu 容器影像,其中包括新的 APT 包:
讓我們來看看規模性獲勝。以下所有大小都是未壓縮的(在磁碟上,不是登錄檔/線路大小)。
首先,runtime-deps
層。
- Ubuntu 22.04 (Jammy):
112MB
- Chiseled Ubuntu 22.04 (Jammy):
12.9MB
在頻譜的另一端,aspnet 層。
- Ubuntu 22.04 (Jammy):
213MB
- Chiseled Ubuntu 22.04 (Jammy):
104MB
多麼驚人的區別!Canonical 的人已經想出瞭如何從這些影像中刪除 100MB 的二進位制檔案和其他內容。當我們第一次開始交談時,我們不知道我們會談論如此大的差異!
細心的讀者會注意到chiseled aspnet
比現有的 runtime-deps
層小。這真是太好了。
諮詢Alpine的樣子是合理的。這是一個較新的發行版,從一開始就設計為超小型和元件化。對於 runtime-deps:6.0-alpine
,Alpine 為 9.84MB
,對於 aspnet:6.0-alpine
,為 100MB。這些是未壓縮並且令人印象深刻的數字。這是 Alpine 如此受歡迎的一個關鍵原因(也是我們多年來為它釋出 .NET 影像的原因)。
Alpine 很棒(我們也是這些人的朋友),但它並不適合所有人和每個應用程式,因為它使用 musl,一種不同(且不相容)的 libc
變體。這僅在您的應用程式包含本機庫時才重要。如果沒有(大多數 .NET 應用程式沒有),則無需擔心此細節。.NET 產品本身很樂意與 musl
或 glibc 一起執行,並且每個 PR 都在 dotnet/runtime 測試上執行。
從這個角度來看,如果您使用 Ubuntu 進行開發並且一直希望將小型 Ubuntu 投入生產,這確實是個好訊息。您現在擁有從開發盒到雲的直接路徑,沒有任何發行版相容性問題。看到 Ubuntu 與 Alpine 在同一個球場上,真是令人驚奇(也非常令人驚訝)。向 Canonical 的人們致敬,感謝他們在工程方面取得的巨大成就。
值得一提的是,Chainguard 正在尋找最小的容器影像,以確保未來的安全。該專案已用完 distroless GitHub org。我們正在關注這個專案,很高興看到人們對更小、更安全的容器影像更感興趣。我們相信最小 + 非root容器影像是未來。
就像我們的 Alpine 影像一樣,我們選擇不包括 ICU。它可能會使影像的大小增加一倍。這意味著我們啟用了全球化不變模式。對於某些應用程式來說,這很好,而且規模上的勝利也很棒。對於其他人來說,這是一個交易破壞者。我們可能需要根據反饋調整這部分計劃。我們已經記錄了將 ICU 新增到影像中的模式。
讓我稍微演示一下這些影像,以說明這些影像是如何(有意)受到限制的。
% docker run --rm mcr.microsoft.com/dotnet/nightly/runtime-deps:6.0-jammy-chiseled-amd64
docker: Error response from daemon: No command specified.
See 'docker run --help'.
讓我們再試一次。
% docker run --rm mcr.microsoft.com/dotnet/nightly/runtime-deps:6.0-jammy-chiseled-amd64 bash
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown.
嗯?這是怎麼回事?他們不工作!這才是重點。這些是類似裝置的容器影像。它們被剝離到最低限度。他們只是做你設計他們要做的事情。這就是使它們更安全的原因。如果這種體驗不舒服,您可以隨時使用常規的 Ubuntu 影像。我們將繼續提供它們。他們不會消失。
對於runtime和 aspnet 影像,我們決定使用 dotnet –info 作為 ENTRYPOINT,以使體驗更加友好和有用。
% docker run --rm mcr.microsoft.com/dotnet/nightly/runtime:6.0-jammy-chiseled
global.json file:
Not found
Host:
Version: 6.0.8
Architecture: arm64
Commit: 55fb7ef977
.NET SDKs installed:
No SDKs were found.
.NET runtimes installed:
Microsoft.NETCore.App 6.0.8 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Download .NET:
https://aka.ms/dotnet-download
Learn about .NET Runtimes and SDKs:
https://aka.ms/dotnet/runtimes-sdk-info
我們不提供chiseled SDK 影像。因為並沒有明顯的強烈需求。事實上,chiseled SDK 影像在某些情況下可能很難使用。您可以繼續使用現有的 Jammy SDK 影像:mcr.microsoft.com/dotnet/sdk:6.0-jammy
。如果需要chiseled SDK 影像,我們很樂意重新考慮。
使用chiseled容器影像
對於大多數應用程式來說,使用這些新的容器影像不會對 Dockerfile 的外觀產生任何顯著影響。我們更新了我們的示例以使用這些新的容器影像:
我將向您展示使用 dotnetapp 是很容易的事情。
Dockerfile 幾乎沒有什麼不同。
FROM mcr.microsoft.com/dotnet/sdk:7.0-jammy AS build
WORKDIR /source
# 複製 csproj 並恢復為不同的層
COPY *.csproj .
RUN dotnet restore --use-current-runtime
# 複製和釋出應用程式和庫
COPY . .
RUN dotnet publish -c Release -o /app --use-current-runtime --self-contained false --no-restore
# 最後階段/影像
FROM mcr.microsoft.com/dotnet/nightly/runtime:7.0-jammy-chiseled
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "dotnetapp.dll"]
只有最後的 FROM
語句與我們的標準 Ubuntu Dockerfile 真正不同。
我現在將構建示例:
rich@MacBook-Air-2 dotnetapp % pwd
/Users/rich/git/dotnet-docker/samples/dotnetapp
rich@MacBook-Air-2 dotnetapp % docker build -t dotnetapp-chiseled -f Dockerfile.chiseled .
rich@MacBook-Air-2 dotnetapp % docker images | grep dotnetapp-chiseled
dotnetapp-chiseled
latest bf7e125bd182 20 seconds ago 90.5MB
注意:我沒有使用任何 .NET 修剪功能。當然,這個影像可以做得更小。讓我們啟動容器:
rich@MacBook-Air-2 dotnetapp % docker run --rm dotnetapp-chiseled
42
42 ,d ,d
42 42 42
,adPPYb,42 ,adPPYba, MM42MMM 8b,dPPYba, ,adPPYba, MM42MMM
a8" `Y42 a8" "8a 42 42P' `"8a a8P_____42 42
8b 42 8b d8 42 42 42 8PP""""""" 42
"8a, ,d42 "8a, ,a8" 42, 42 42 "8b, ,aa 42,
`"8bbdP"Y8 `"YbbdP"' "Y428 42 42 `"Ybbd8"' "Y428
.NET 7.0.0-preview.7.22375.6
Linux 5.10.104-linuxkit #1 SMP PREEMPT Thu Mar 17 17:05:54 UTC 2022
OSArchitecture: Arm64
ProcessorCount: 4
TotalAvailableMemoryBytes: 3.83 GiB
然後,讓我們嘗試進入:
rich@MacBook-Air-2 dotnetapp % docker run --rm --entrypoint bash dotnetapp-chiseled
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown.
rich@MacBook-Air-2 dotnetapp % docker run --rm --entrypoint apt dotnetapp-chiseled install -y bash curl
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "apt": executable file not found in $PATH: unknown.
我的“red team”技能讓我失望了。請注意,docker exec
將具有相同的結果。現在我將更詳細地描述Chiseled影像,正如您在實際中看到的那樣。
Chiseled Ubuntu 容器
Chiseled Ubuntu 容器 是 Canonical 對 distroless 概念的詮釋,最初由 Google 推廣。在最初的實現中,分發被剝離,只安裝了必要的包。Chiseling 更進一步,只在每個包中安裝必要的目錄和檔案。
最初實施的另一個挑戰是它不一定得到任何一方的支援。Chiseled Ubuntu 容器 是一流的 Canonical 可交付成果。這意味著您可以使用超小型容器影像並作為 Canonical 客戶獲得支援。
感謝 Google 讓我們所有人走上這條道路。
如前所述,這種方法有很多價值:
- 超小影像(減小尺寸和攻擊面)
- 沒有包管理器(避免一整類攻擊)
- 無外殼(避免一整類攻擊)
Chiseled Ubuntu 容器目前處於預覽階段。當它們穩定並在生產中得到支援時,我們將另行釋出公告。
非 root影像
我們已經使用非 root 使用者配置了所有新的 .NET Chiseled Ubuntu 容器。這些影像不包含 root
使用者或包含提升 root 許可權的命令,例如 sudo
或 su
。這意味著無法執行需要 root
的功能和操作。
除了刪除像 bash
這樣的 shell 之外,非 root 影像也是一種額外的安全緩解措施。非 root 影像在邏輯上是獨立的,並且補充了沒有 root 執行的守護程式。特權的每一次減少都會有所幫助。
如果您需要訪問特權資源,可以在 Dockerfile
中新增 root
使用者。你不會被阻止,但這是您要做出的特定安全決定。
Chiseled影像類似於裝置,不是通用的。我們覺得他們為我們提供了最終交付非 root影像的機會。這為我們未來的政策提供了依據。類似裝置的影像將作為非 root 使用者交付,而通用影像將根據基本影像的策略(可能使用 root
使用者配置)進行交付。然而,Canonical 的這個專案啟發了我們尋找一箇中間選項,即提供不支援 root 的影像。
安全的供應鏈
Canonical 制定了一個安全流程,可將 Ubuntu 虛擬機器影像直接交付到 Azure 以供客戶使用。我們突然想到,Canonical 可以對我們用來構建基於 Ubuntu 的 .NET 影像(常規和 Chiseled)的 Ubuntu 容器基礎影像做同樣的事情。這就是我們現在使用的,而不是從 Docker Hub 中提取。我們現在為所有具有已知保管/出處的 Canonical 資產建立了有效的零距離供應鏈。
我們正在做與共享 CVE 修復類似的事情。我們有一個共享的私有虛擬單聲道儲存庫,用於共享每月補丁。它也與 Red Hat 共享。這意味著我們可以共同努力,以協調的方式在正確的時間進行正確的修復。
.NET 容器影像尚未簽名,但即將推出。我們會定期努力提高我們以安全為中心的能力。
支援
Canonical 和 Microsoft 一直在合作,為您提供更好的體驗。這包括支援。您可以在熟悉的 .NET 儲存庫中報告問題,例如 dotnet/core 和 dotnet/runtime。如果您想要商業支援,您應該從 Canonical 支援開始。Canonical 是支援 Ubuntu 軟體包的最佳場所。Canonical 可能會根據需要聯絡 Microsoft 以協助解決問題。
在 Canonical 提供的 .NET 包中發現漏洞的安全研究人員仍然有資格參加 Microsoft .NET Bounty Program。
Microsoft 繼續在其 packages.microsoft.com 原始碼中維護 Ubuntu 的 .NET 包,我們打算在未來繼續這樣做。對於大多數使用者,我們建議使用 Ubuntu Jammy+ 附帶的 dotnet6 包。這就是我所做的。這與我們為 Red Hat 使用者提供的指南相同。
注意:現在 .NET 6 已包含在 Ubuntu 中,請檢視我們關於在 Ubuntu 22.04 上使用 packages.microsoft.com 的建議。
繼續使用 Microsoft 軟體包有兩個主要原因:
- 您希望使用來自 Microsoft 的 .NET 版本,而不是任何其他供應商。
- Microsoft 軟體包針對更高版本的 .NET SDK 功能頻段(如
6.0.4xx
),而原始碼構建跟蹤6.0.1xx
。這對 Windows 使用者更相關,但對某些 Linux 使用者可能很重要。
新軟體包可用於 .NET 6+ 和 Ubuntu 22.04+。不支援以前的 .NET 和 Ubuntu 版本(使用新軟體包)。您必須使用現有的 packages.microsoft.com
提要才能在早期 Ubuntu 版本上使用 .NET。此外,Ubuntu 22.04 不支援早期的 .NET 版本,因為它們不支援 OpenSSL v3。
下一步計劃
我們已經發現了許多使 Canonical 更容易使用 .NET 原始碼的機會。我們將在短期內專注於這些。這些改進還將使其他從原始碼構建和分發 .NET 的使用者受益。
我們最近為 .NET 設定了一個發行版維護組。Canonical 是該組的成員。我們已經開始在該論壇中討論潛在的原始碼構建改進。歡迎其他發行版(從原始碼構建 .NET)加入。有關詳細資訊,請聯絡 dotnet@microsoft.com。
Canonical 開始支援 x64 並將很快為 Arm64 新增 .NET 包。對於需要支援多種主線晶片架構的行業來說,這是一個激動人心的時刻。Ubuntu 和 .NET 在支援多種架構方面有著悠久的歷史。
.NET 已經開源 5 年多了。我們與 Canonical 的合作在我們 GitHub 專案的早期階段感覺是遙不可及。我們已經學到了很多關於如何構建 OSS 專案以便它成為 Linux 發行版候選者的知識。這要感謝教給我們很多東西的其他合作伙伴,尤其是 Fedora 和 Red Hat。回顧過去,很容易看出,現在開源、信任和行業關係比我們剛開始時更為重要。我們很高興也很榮幸能與 Canonical 合作。