我們在撰寫 .NET 的時候,有許多「組態設定」可以輕易的透過「環境變數」來進行調整或變更,這裡同時也包含了 ASP.NET Core 內建的許多 ASPNETCORE_
開頭的內建環境變數名稱,可以幫忙調整許多 .NET 與 ASP.NET Core 的預設行為。今天這篇文章我就來整理一下有哪些可以用!
認識 ASP.NET Core 的宿主環境 (Host)
ASP.NET Core 有兩種宿主環境,不同的宿主環境通常會定義一些環境變數來幫助你調整環境的參數,而環境變數區分成兩個不同的名稱前綴 (Prefix):分別為:
-
.NET Generic Host
通常用來提供 .NET 應用程式一些重要的基礎設定,例如 Dependency injection (DI)、Logging、Configuration、IHostedService implementations 等等,通常用在背景服務類型的應用程式中。
你在執行 CreateDefaultBuilder()
的時候,會載入 DOTNET_
開頭的環境變數。
參見: 介紹幾個 .NET SDK、.NET CLI 與 .NET runtime 執行時的好用環境變數
-
ASP.NET Core Web Host
除了 .NET 應用程式重要的基礎設定外,執行 AAS.NET Core 網站還需要一些額外的設定,例如網站伺服器相關的設定,像是 Kestrel 或 IISIntegration 之類的。
在載入 WebHostBuilder
的時候,會載入 ASPNETCORE_
開頭的環境變數。
參見: ASP.NET Core Web Host
ASP.NET Core Web Host 常見的環境變數
大家應該都知道 ASP.NET Core 內建一套效率極高的 Kestrel 網站伺服器,所有 ASP.NET Core 在執行的時候都少不了它,然而我們在啟動 Kestrel 的時候,就有許多可以設定的地方,以下我列出幾個相對常用的環境變數設定。
-
ASPNETCORE_ENVIRONMENT
我想這個應該是每位 ASP.NET Core 開發人員都該知道的環境變數,非常實用!
這個 ASPNETCORE_ENVIRONMENT
環境變數會用來幫你切換不同的環境(Environment),透過「環境」的管理,可以幫助你在執行時識別不同環境下的資訊,甚至於可以指定不同環境下的組態或應用程式邏輯。
參見: Use multiple environments in ASP.NET Core
-
ASPNETCORE_URLS
我們在用 dotnet run
啟動 ASP.NET Core 在啟動的時候,會先去查找一個 Properties/launchSettings.json
檔案,找到裡面的 profiles.設定檔名稱.applicationUrl
屬性,並以這個屬性指定的 host
與 port
來啟動網站,其設定的格式為 https://localhost:7087;http://localhost:5046
。如下範例:
{
"profiles": {
"w1": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7087;http://localhost:5046",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
然而,在你透過 dotnet publish
發行網站後,就不會再去讀取 Properties/launchSettings.json
檔案,取而代之的,就是去讀取 ASPNETCORE_URLS
環境變數,而且設定值的格式是一樣的,以下是設定範例:
ASPNETCORE_URLS=https://+:443;http://+:80
這裡的 +
(加號) 用來綁定本機的所有網路介面 (network interface),而 https://
預設會自動載入 ASP.NET Core 內建的自簽憑證。
注意: 早期的 ASP.NET Core 版本使用 ASPNETCORE_SERVER.URLS
環境變數,不過已經棄用,使用上要注意,建議改用 ASPNETCORE_URLS
環境變數。
-
ASPNETCORE_Kestrel__Certificates__Default__Path
與 ASPNETCORE_Kestrel__Certificates__Default__Password
如果 ASPNETCORE_URLS
環境變數指定了 https://
通訊協定,預設會自動載入 ASP.NET Core 內建的自簽憑證,不過在正式環境下,我們通常會使用正式憑證,而這兩個環境變數就是為此而生。
我們可以練習透過 mkcert 快速建立一個 PKCS#12 格式的憑證 (PFX):
mkcert -pkcs12 localhost
這個命令會產生 localhost.p12
檔案,預設密碼為 changeit
然後我們就可以設定環境變數如下:
ASPNETCORE_Kestrel__Certificates__Default__Path='localhost.p12'
ASPNETCORE_Kestrel__Certificates__Default__Password='changeit'
-
ASPNETCORE_CONTENTROOT
ASP.NET Core 在啟動的時候,預設會找主程式當前的路徑作為內容(Content)的根目錄,這裡的 Content 指的是 ASP.NET Core 應用程式部署時所有的「內容」,也就是所有的 *.dll
所在的那些資料夾內容。
當你想在啟動應用程式的時候,選用另一個資料夾當作載入組件(assembly)的依據,你才需要指定這個 ASPNETCORE_CONTENTROOT
環境變數。
有個實際的案例是,當你的 ASP.NET Core 應用程式是部署在 Windows 服務時,預設 Windows Service 會以 C:\Windows\System32
為工作目錄,這也意謂著你的 ASP.NET Core 應用程式在執行的時候,會無法載入正確的 DLL 檔案,那就是因為 CONTENTROOT
路徑錯誤導致的。解決方法就是額外指定 ASPNETCORE_CONTENTROOT
環境變數即可。詳見: Host ASP.NET Core in a Windows Service
-
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
這裡的 ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
可以指定 ASP.NET Core 應用程式的啟動組件(startup assemblies),他會在應用程式啟動時,自動找出指定組件中的 HostingStartup
attribute,並在應用程式啟動時執行特定程式碼!
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
多個組件請用 ;
(分號) 分隔不同組件!
這是一種在 .NET 環境下動態載入程式碼的一種進階技巧,詳見 Use hosting startup assemblies in ASP.NET Core 文章說明。
參見: 啟用 Razor 執行階段編譯 (Enable Razor runtime compilation) 技術細節探索
-
ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
由於 hosting startup assemblies 可以寫死在程式中:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseSetting(
WebHostDefaults.HostingStartupExcludeAssembliesKey,
"{ASSEMBLY1;ASSEMBLY2; ...}")
.UseStartup<Startup>();
});
如果你想要在啟動時動態排除特定組件,就可以使用 ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
這個環境變數。
-
ASPNETCORE_PREVENTHOSTINGSTARTUP
如果你想要在啟動時完全關閉 hosting startup assemblies 機制,就可以使用 ASPNETCORE_PREVENTHOSTINGSTARTUP
這個環境變數。
ASPNETCORE_PREVENTHOSTINGSTARTUP=1
-
ASPNETCORE_HTTPS_PORT
當你使用了 HTTPS Redirection Middleware (UseHttpsRedirection
) 強迫將所有 HTTP 要求自動轉向到 HTTPS 通訊協定,預設會自動轉向到 Port 443
,如果不是這個 Port 的話,就要透過 ASPNETCORE_HTTPS_PORT
環境變數來指定。
ASPNETCORE_HTTPS_PORT=8443
或是你也可以將 https_port
設定加在 appsettings.json
設定檔中:
{
"https_port": 443,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
-
ASPNETCORE_SHUTDOWNTIMEOUTSECONDS
當 ASP.NET Core 應用程式呼叫 IApplicationLifetime.ApplicationStopping 或在嘗試停止應用程式的過程,因為特定原因導致無法關閉時,可以設定等待幾秒就要強制關閉!(預設 5
秒)
ASPNETCORE_SHUTDOWNTIMEOUTSECONDS=10
-
ASPNETCORE_STARTUPASSEMBLY
在 ASP.NET Core 5 之前都有個 Startup
類別,雖然在 ASP.NET Core 6 的 Minimal APIs 看不到了,但事實上你還是可以定義這個類別,並使用早期的 API 進行定義。如果你想將 Startup
類別寫在完全不同的另一個組件下,就可以利用 ASPNETCORE_STARTUPASSEMBLY
環境變數來動態指定啟動類別 (Startup class),非常方便!
-
ASPNETCORE_WEBROOT
在 ASP.NET Core 網站中,如果要載入靜態網站資源,預設都會放在 wwwroot
資料夾下,而這個資料夾名稱可以很簡單的透過 ASPNETCORE_WEBROOT
環境變數來改變,完全不用修改程式碼。
ASPNETCORE_WEBROOT=public
一些相對罕見的環境變數
-
ASPNETCORE_TEMP
在 ASP.NET Core 的核心程式中,所有會用到「暫存資料夾」的地方,都會優先判斷式否有這個 ASPNETCORE_TEMP
環境變數,如果有的話,就會以環境變數指定的資料夾路徑作為暫存檔案的存放地點。如果沒有,就會直接呼叫 Path.GetTempPath()
取得系統預設的暫存資料夾。
ASPNETCORE_TEMP=G:\TEMP
-
ASPNETCORE_FORWARDEDHEADERS_ENABLED
如果你想在 Kesntel 前面加上一個負載平衡器,而且負載平衡器不是用 IIS 的話,你就可能會用到這個環境變數。
詳細的用法參見 Forward the scheme for Linux and non-IIS reverse proxies 文章說明。
ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
如果你的網站部署在 Azure App Service on Linux 或 Web App for Containers 上,也只要在「應用程式設定」的地方加入一個 ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
設定到網站上即可,程式完全不用修改就可以啟用。參見: Forwarded Headers Middleware Updates in .NET Core 3.0 preview 6
ASP.NET Core Module (ANCM) for IIS 相關環境變數
-
ASPNETCORE_PORT
這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來指定 Out of proccess 運作的 Kestrel 要跑在哪個 Port 上面。
注意: 你幾乎不會自行設定這個環境變數!
-
ASPNETCORE_APPL_PATH
這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來指定應用程式所在路徑。
注意: 你幾乎不會自行設定這個環境變數!
-
ASPNETCORE_TOKEN
這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來指定 IIS 與 Kestrel 之間的 Token。
注意: 你幾乎不會自行設定這個環境變數!
-
ASPNETCORE_IIS_HTTPAUTH
這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來指定 Kestrel 該如何處理 AUTH 要求。
注意: 你幾乎不會自行設定這個環境變數!
-
ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED
這個環境變數只會用在與 IIS 整合的時候,IIS 在啟動 Kestrel 的時候,會偷偷傳入這個環境變數,用來告訴 Kestrel 這台 IIS 是否支援 WebSockets 協定。
注意: 你幾乎不會自行設定這個環境變數!
-
ASPNETCORE_MODULE_DEBUG
當你在 Visual Studio 使用 IIS Express 開發時,這個環境變數可以讓你將 ASP.NET Core Module 的偵錯資訊輸出到 Console 畫面上。
ASPNETCORE_MODULE_DEBUG=console
已經不再使用的環境變數
-
ASPNETCORE_SERVER.URLS
這個環境變數已經被 ASPNETCORE_URLS
取代。
-
ASPNET_ENV
這個環境變數已經被 ASPNETCORE_ENVIRONMENT
取代。
-
Hosting:Environment
這個環境變數已經被 ASPNETCORE_ENVIRONMENT
取代。
-
ASPNETCORE_MANAGEMENTPORT
在 ASP.NET Core 5.0 以前,有個 ASPNETCORE_MANAGEMENTPORT
環境變數,用來指定健康檢測端點的 Port 埠號要用哪一個,讓正式對外的 Port 與健康檢測的 Port 分開,增強安全性。不過從 ASP.NET Core 6.0 開始,就不太需要這個設定了,直接寫死在程式中就好,如下範例:
app.MapHealthChecks("/healthz").RequireHost("*:5001");
想瞭解 ASP.NET Core 5.0 的設定方式,參見 Health checks in ASP.NET Core | Microsoft Docs
其他可能會用到的環境變數
如果不想載入 ASPNETCORE_ 環境變數
以下範例程式我從 dotnet/aspnetcore Repo 的 src\Hosting\Hosting\test\GenericWebHostBuilderTests.cs
測試程式中擷取出來的,只要將 webHostBulderOptions.SuppressEnvironmentConfiguration
設定為 true
即可。
[Fact]
public void CanSuppressAspNetCoreEnvironmentVariables()
{
var randomEnvKey = Guid.NewGuid().ToString();
Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, "true");
using var host = new HostBuilder()
.ConfigureWebHost(_ => { }, webHostBulderOptions =>
{
webHostBulderOptions.SuppressEnvironmentConfiguration = true;
})
.Build();
var config = host.Services.GetRequiredService<IConfiguration>();
Assert.Null(config[randomEnvKey]);
Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, null);
}
2024-05-05: 補充說明 .NET CLI 的使用技巧
本篇文章介紹的雖然都是 ASP.NET Core 的環境變數,但其實在透過 .NET CLI 執行 ASP.NET Core 應用程式的時候,其實也可以透過命令列的方式直接取代這些環境變數,而且載入的優先權比環境變數高。以下是幾個常見的例子 (以 dotnet run
為例):
-
啟動網站時指定環境名稱
dotnet MyApp.dll --environment=Production
-
啟動網站時指定網站的網址與埠號
dotnet MyApp.dll --urls="https://localhost:5001;http://localhost:5000"
-
啟動網站時顯示所有的記錄訊息
dotnet MyApp.dll --Logging:Console:LogLevel:Default=Trace
-
啟動網站時載入 Kestrel 所需的 TLS 憑證
dotnet MyApp.dll --Kestrel:Certificates:Default:Path='localhost.p12' --Kestrel:Certificates:Default:Password='changeit' --urls='https://*:5001'
-
啟動網站時變更 ContentRoot 路徑
這個需求在 Host ASP.NET Core in a Windows Service 的時候常見。
dotnet MyApp.dll --contentRoot=g:\publish
-
啟動網站時變更預設的 HTTPS 轉向埠號
當你的 Kestrel 監聽多個 HTTPS Port 時,或是網站位於 Reverse Proxy 後面時,就有可能需要設定這個參數。
dotnet MyApp.dll --urls='https://*:5001;http://*:5000;https://*:5003' --https_port=5003
相關連結