Docker:多階段構建 ASP.NET Core 應用鏡像

本文選自『.NET大牛之路』知識星球,發布于2022年05月25日。

今天我們一起來寫 Dockerfile 構建一個 ASP.NET Core 應用鏡像,同時還會將鏡像發布到 Docker Hub 倉庫。

1創建示例 Web 應用程序

為了演示,我們先創建一個 ASP.NET Core 應用程序:

PS D:\Samples> dotnet new web -o AspNetDemo
已成功創建模板“ASP.NET Core Empty”。正在處理創建后操作...
在 D:\Samples\AspNetDemo\AspNetDemo.csproj 上運行 “dotnet restore”...正在確定要還原的項目…已還原 D:\Samples\AspNetDemo\AspNetDemo.csproj (用時 77 ms)。
已成功還原。

項目創建好了,檢查一下看看是否能正常運行:

PS D:\Samples> cd .\AspNetDemo\
PS D:\Samples\AspNetDemo> dotnet run
正在生成...
info: Microsoft.Hosting.Lifetime[14]Now listening on: https://localhost:7000
info: Microsoft.Hosting.Lifetime[14]Now listening on: http://localhost:5276
info: Microsoft.Hosting.Lifetime[0]Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]Content root path: D:\Samples\AspNetDemo\

打開輸出提示的地址 https://localhost:7000,瀏覽器正常顯示 “Hellow World”,說明應用程序正常。

然后我們在 AspNetDemo 目錄中添加一個 Dockerfile 文件,為下文作準備。

2依賴本地環境構建鏡像

我們可以在 DockerHub 找到我們需要的 ASP.NET Core 運行時基礎鏡像:

030a044c84fdd921f7cad1187c1adec9.png

現在,要把我們的 AspNetDemo 應用通過鏡像的方式發布,利用我們之前學過的 Docker 知識,我們很自然會想到這樣的思路:通過 dotnet publish 命令打包發布文件,然后把發布文件復制到 ASP.NET Core 運行時基礎鏡像中。

于是我們先在本地(bin/Publish 目錄)生成好發布文件:

PS D:\Samples\AspNetDemo> dotnet publish -c release -o bin/Publish正在確定要還原的項目…所有項目均是最新的,無法還原。AspNetDemo -> D:\Samples\AspNetDemo\bin\release\net6.0\AspNetDemo.dllAspNetDemo -> D:\Samples\AspNetDemo\bin\Publish\

然后 Dockerfile 文件可以這樣寫:

FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY bin/Publish .
ENTRYPOINT ["dotnet", "AspNetDemo.dll"]

開始構建鏡像:

PS D:\Samples\AspNetDemo> docker build -t aspnetdemo .
[+] Building 0.8s (8/8) FINISHED
...PS D:\Samples\AspNetDemo> docker image ls
REPOSITORY           TAG           IMAGE ID       CREATED          SIZE
aspnetdemo           latest        62c8c40cbc70   33 seconds ago   208MB

試試在本地使用該鏡像運行容器:

PS D:\Samples\AspNetDemo> docker run -d?-p?80:80 aspnetdemo
a4d67637585c67384a6c7a3a9e8a39acc345253730ce22f39b7afdedec353397

打開瀏覽器訪問 localhost 效果如下:

84b7e5993cd9b2c49df1362aea8316a1.png

看起來還不錯。

3多階段構建鏡像

相信很多童鞋已經想到了上面依賴本地的開發環境構建鏡像存在的問題了。我們前面構建的 aspnetdemo 鏡像,是先在本地生成好了發布的文件再復制到鏡像里的。這樣存在的一個明顯問題是,其他人如果環境和我們的不一致,構建的鏡像就可能是一個有問題的鏡像,甚至直接構建失敗。這種例子很常見,比如同一套代碼,在你的機器上可以正常運行,因為環境不同(比如未安裝指定的軟件、未配置環境變量等),在同事機器上可能就運行不起來。

要避免這種情況,生成發布文件甚至是開發測試的過程,就不能依賴本地的開發環境來做了。即,我們要把生成發布文件的過程也放到 Dockerfile 中去做。

但由于 ASP.NET Core 運行時鏡像不具有編譯的能力,所以我們需要把基礎鏡像換成 .NET SDK 鏡像。這樣就可以了嗎?這樣也不是不可以,但是 .NET SDK 鏡像會比 ASP.NET Core 運行時鏡像大很多,我們可以比較一下:

PS D:\Samples\AspNetDemo> docker image ls
REPOSITORY                         TAG                IMAGE ID       CREATED             SIZE
mcr.microsoft.com/dotnet/sdk       6.0                d3863aa157b5   6 days ago          736MB
mcr.microsoft.com/dotnet/aspnet    6.0                683c56113596   8 weeks ago         208MB

可以看到 .NET SDK 鏡像比 ASP.NET Core 運行時鏡像大了 500 多 MB,這顯然會大大降低鏡像發布的速度。

這時候我們就需要用到多階段構建了,思路是把鏡像的構建分成多個階段,不同的階段使用不同的基礎鏡像,前面的所有階段都只是為最后一個階段做準備,最終發布的也是最后一個階段。

下面使用多階段構建來改寫 Dockerfile,參考如下:

# 階段一:build
# 選擇 SDK 鏡像用于編譯源碼和生成發布文件
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /source
# 復制源代碼
COPY *.csproj *.cs .
# 生成發布文件
RUN dotnet publish -c release -o /app# 階段二:final
# 使用 ASP.NET Core 運行時鏡像
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS final
WORKDIR /app
# 從 build 階段復制生成好的發布文件
COPY --from=build /app .
ENTRYPOINT ["dotnet", "AspNetDemo.dll"]

這個 Dockerfile 還可以繼續優化,我將在下一節課講鏡像的優化時再改寫它。

為了觀察效果,我們稍微修改一下 Program.cs 中 Http 響應的內容:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();app.MapGet("/", () => "v2: Hello Docker!");app.Run();

再次構建并運行容器:

PS D:\Samples\AspNetDemo> docker image build -t aspnetdemo .
[+] Building 5.8s (13/13) FINISHED
...PS D:\Samples\AspNetDemo> docker image ls
REPOSITORY                    TAG             IMAGE ID       CREATED          SIZE
aspnetdemo                    latest          d6a596b1514d   55 seconds ago   208MBPS D:\Samples\AspNetDemo> docker run -d?-p?80:80 aspnetdemo
e9b9045299f5a3b7614cb3cee91b00ebe67a066b1f65eff46369fa1844b1d824

打開瀏覽器訪問 localhost 驗證一下效果:

51f3c081066767efcd639b06113a2f39.png

可以看到我們雖然把生成發布文件的過程放到了 Dockerfile 中,但通過多階段構建,最后構建出來的鏡像也是 208M,和前面一樣。

所以,我們可以把編譯運行所需要的環境配置都寫到 Dockerfile 中,這樣可以保證任何一臺機器都可以順利構建鏡像,且不管誰來構建,相同的源代碼構建出來的鏡像都是一樣的。

4發布鏡像

最后我們可以把構建好的鏡像發布到自己的 Docker 倉庫,這里以 Docker Hub 為例(實際生產環境請發布到自己的私有倉庫)。

先在 Docker Hub 創建一個 Repositry:

c52615f737793afd6f48f757dc127bd2.png

推送鏡像前,需要在本地登錄一下:

PS D:\Samples\AspNetDemo> docker login
Authenticating with existing credentials...
Login Succeeded

然后給我們的鏡像打上一個標簽(默認是latest):

PS D:\Samples\AspNetDemo> docker tag aspnetdemo liamwang/aspnetdemo
# 也可以指定標簽:docker tag aspnetdemo:latest liamwang/aspnetdemo:latest

然后推送到遠程倉庫:

PS D:\Samples\AspNetDemo> docker push liamwang/aspnetdemo
The push refers to repository [docker.io/liamwang/aspnetdemo]
e68e6a7d93c2: Pushed
ace5cec48f84: Pushed
17aff088b762: Pushed
9a515fdf7f03: Pushed
c4d9ca739af5: Pushed
3f94255da7c2: Pushed
608f3a074261: Pushed
latest: digest: sha256:dc479f2e52d48b3a81c0a83b5c740a085b299d046f268d21bb61c5bcfa5ae608 size: 1787
PS D:\Samples\AspNetDemo>

這步完成后,可以在 Docker Hub 上看到已發布的鏡像:

f16302effb5e5c673f4af66f252a6cd3.png

然后我們可以到任意一臺服務器 pull 該鏡像運行容器了。

5小結

本節課我們以 ASP.NET Core 應用為例,先是用依賴本地環境的方式構建了鏡像,分析了這種方式存在的問題,然后講了如何使用多階段構建來解決這個問題,最后演示了如何把已經構建好的鏡像發布到自己的 Docker 鏡像倉庫。

下節課我們來解析和理解鏡像的分層,理解鏡像的分層可以幫助我們優化鏡像的構建過程,也有助于制作更優質的鏡像。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/285451.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285451.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285451.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[轉]【JAVA各版本特性】JAVA 1.0

閑來想了解下各版本之間的特性,搜索沒有最新的特性說明,故想寫一份。廢話不多說。 JDK Version 1.0 1996-01-23 Oak(橡樹) 初代版本,偉大的一個里程碑,但是是純解釋運行,使用外掛JIT,性能比較差&#xff0…

【數據庫原理及應用】經典題庫附答案(14章全)——第八章:數據庫并發控制

【數據庫原理及應用】經典題庫附答案(14章全)——第一章:數據庫基礎知識 【數據庫原理及應用】經典題庫附答案(14章全)——第二章:關系數據庫知識 【數據庫原理及應用】經典題庫附答案(14章全)——第三章:結構化查詢語言SQL 【數據庫原理及應用】經典題庫附答案(14章…

Tomcat(Windows)

百度云:鏈接:http://pan.baidu.com/s/1pKYrf79 密碼:56t0官網下載網址:http://archive.apache.org/dist/tomcat/tomcat-9/v9.0.0.M13/bin/ 轉載于:https://www.cnblogs.com/haxianhe/p/9271103.html

北京Uber優步司機獎勵政策(3月11日)

滴快車單單2.5倍,注冊地址:http://www.udache.com/ 如何注冊Uber司機(全國版最新最詳細注冊流程)/月入2萬/不用搶單:http://www.cnblogs.com/mfryf/p/4612609.html 優步獎勵低/不掙錢/怎么辦?看這里:http://www.cnblogs.com/mfry…

【招聘(廣州)】成功易(廣州).Net Core中高級開發工程師

成功易(廣州)信息技術有限公司簡介成功易是一家集團性公司,創立于2002年,總部位于北京,旗下擁有7家子公司。廣州成功易成立于2019年,人員逐漸增長150人,組織架構完善, 我們是騰訊廣告…

【數據庫原理及應用】經典題庫附答案(14章全)——第九章:數據庫安全性

【數據庫原理及應用】經典題庫附答案(14章全)——第一章:數據庫基礎知識 【數據庫原理及應用】經典題庫附答案(14章全)——第二章:關系數據庫知識 【數據庫原理及應用】經典題庫附答案(14章全)——第三章:結構化查詢語言SQL 【數據庫原理及應用】經典題庫附答案(14章…

webstrom使用方法

一、設置file-settings- -color&fonts設置,字體 主體 -file and code templates模板ctrlr 查找,替換1 雙擊shift 快速查找2 file -new project 新建文件夾3 file-new 新建html css js等4 右鍵-local history 查看歷史5 雙擊選擇某個元素,…

ERROR 1045 (28000): Access denied for user 'ODBC'@'localhost' 解決Mysql錯誤

1、停止 服務 PS C:\WINDOWS\system32> net stop mysql mysql 服務正在停止. mysql 服務已成功停止。2、執行 mysqld --shared-memory --skip-grant-tables PS C:\WINDOWS\system32> mysqld --shared-memory --skip-grant-tables ------以下操作 另外打開一個 終端--…

xcode 設置快捷鍵 整行上下移動

2019獨角獸企業重金招聘Python工程師標準>>> 設置整行代碼上下移動:找到Xcode中的自帶的配置文件:/Applications/Xcode.app/Contents/Frameworks/IDEKit.framework/Versions/A/Resources/IDETextKeyBindingSet.plist用文本編輯IDETextKeyBind…

【數據庫原理及應用】經典題庫附答案(14章全)——第十章:數據庫完整性

【數據庫原理及應用】經典題庫附答案(14章全)——第一章:數據庫基礎知識 【數據庫原理及應用】經典題庫附答案(14章全)——第二章:關系數據庫知識 【數據庫原理及應用】經典題庫附答案(14章全)——第三章:結構化查詢語言SQL 【數據庫原理及應用】經典題庫附答案(14章…

用.Net Core接入微信公眾號開發

Part1前言最近想寫一點基于.Net Core微信公眾號開發的文章Part2測試公眾號申請測試公眾號申請地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?tsandbox/login微信公眾號開發文檔:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html通過微…

騰訊、百度、小米等7家互聯網各大廠的中臺建設怎么樣了?

中臺是真正為前臺而生的平臺(可以是技術平臺,業務能力甚至是組織機構),它存在的唯一目的就是更好的服務前臺規模化創新,進而更好的響應服務引領用戶,使企業真正做到自身能力與用戶需求的持續對接。 以下轉載…

JAVA基礎知識之網絡編程——-基于AIO的異步Socket通信

異步IO 下面摘子李剛的《瘋狂JAVA講義》 按照POSIX標準來劃分IO,分為同步IO和異步IO。對于IO操作分為兩步,1)程序發出IO請求。 2)完成實際的IO操作。 阻塞IO和非阻塞IO都是針對第一步來劃分的,如果發出IO請求會阻塞線程…

基于.NetCore開發博客項目 StarBlog - (13) 加入友情鏈接功能

系列文章基于.NetCore開發博客項目 StarBlog - (1) 為什么需要自己寫一個博客?基于.NetCore開發博客項目 StarBlog - (2) 環境準備和創建項目基于.NetCore開發博客項目 StarBlog - (3) 模型設計基于.NetCore開發博客項目 StarBlog - (4) markdown博客批量導入基于.N…

【數據庫原理及應用】經典題庫附答案(14章全)——第十二章:數據庫技術新發展

【數據庫原理及應用】經典題庫附答案(14章全)——第一章:數據庫基礎知識 【數據庫原理及應用】經典題庫附答案(14章全)——第二章:關系數據庫知識 【數據庫原理及應用】經典題庫附答案(14章全)——第三章:結構化查詢語言SQL 【數據庫原理及應用】經典題庫附答案(14章…

EditPlus 文件查找功能:在指定文件夾,用正則查尋包含指定內容的文件,指定文件類型,并排除特殊文件名文件

單擊菜單欄上的【Search】&#xff08;查找&#xff09;&#xff0c;選擇【Find in Files】&#xff08;在文件中查找&#xff09;命令&#xff1a; 查找項&#xff1a;正則查找video標簽&#xff0c;src為不包含http的mp4 <video src"([^http].*\.mp4)" width&q…

【數據庫原理及應用】經典題庫附答案(14章全)——第十三章:面向對象程數據庫系統

【數據庫原理及應用】經典題庫附答案(14章全)——第一章:數據庫基礎知識 【數據庫原理及應用】經典題庫附答案(14章全)——第二章:關系數據庫知識 【數據庫原理及應用】經典題庫附答案(14章全)——第三章:結構化查詢語言SQL 【數據庫原理及應用】經典題庫附答案(14章…

NOIP2016普及組第三題——海港

題目描述 小K是一個海港的海關工作人員&#xff0c;每天都有許多船只到達海港&#xff0c;船上通常有很多來自不同國家的乘客。 小K對這些到達海港的船只非常感興趣&#xff0c;他按照時間記錄下了到達海港的每一艘船只情況&#xff1b;對于第i艘到達的船&#xff0c;他記錄了這…

7z-linux下解決中文名亂碼的終極辦法

為什么80%的碼農都做不了架構師&#xff1f;>>> linux上安裝7z主要是為了解決中文文件名亂碼的問題&#xff0c;壓縮率還是其次原因 具體安裝看參考網址&#xff0c;建議用源碼方式安裝 官網下載地址&#xff1a;http://www.7-zip.org/download.html 源文件項目地址…

C# .Net 視頻下載功能(本機文件)及轉發下載功能(Http遠程文件)

/*服務器本機文件下載*/ Response.Clear(); Response.ClearContent(); Response.ClearHeaders(); Response.AddHeader("Content-Transfer-Encoding", "binary"); Response.ContentType "application/octet-stream"; Response.ContentEncoding …