The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

ASP.NET Core 6.0 所有可能用到的 ASPNETCORE_* 環境變數總整理

我們在撰寫 .NET 的時候,有許多「組態設定」可以輕易的透過「環境變數」來進行調整或變更,這裡同時也包含了 ASP.NET Core 內建的許多 ASPNETCORE_ 開頭的內建環境變數名稱,可以幫忙調整許多 .NET 與 ASP.NET Core 的預設行為。今天這篇文章我就來整理一下有哪些可以用!

認識 ASP.NET Core 的宿主環境 (Host)

ASP.NET Core 有兩種宿主環境,不同的宿主環境通常會定義一些環境變數來幫助你調整環境的參數,而環境變數區分成兩個不同的名稱前綴 (Prefix):分別為:

  1. .NET Generic Host

    通常用來提供 .NET 應用程式一些重要的基礎設定,例如 Dependency injection (DI)、Logging、Configuration、IHostedService implementations 等等,通常用在背景服務類型的應用程式中。

    你在執行 CreateDefaultBuilder() 的時候,會載入 DOTNET_ 開頭的環境變數。

    參見: 介紹幾個 .NET SDK、.NET CLI 與 .NET runtime 執行時的好用環境變數

  2. ASP.NET Core Web Host

    除了 .NET 應用程式重要的基礎設定外,執行 AAS.NET Core 網站還需要一些額外的設定,例如網站伺服器相關的設定,像是 KestrelIISIntegration 之類的。

    在載入 WebHostBuilder 的時候,會載入 ASPNETCORE_ 開頭的環境變數。

    參見: ASP.NET Core Web Host

ASP.NET Core Web Host 常見的環境變數

大家應該都知道 ASP.NET Core 內建一套效率極高的 Kestrel 網站伺服器,所有 ASP.NET Core 在執行的時候都少不了它,然而我們在啟動 Kestrel 的時候,就有許多可以設定的地方,以下我列出幾個相對常用的環境變數設定。

  1. ASPNETCORE_ENVIRONMENT

    我想這個應該是每位 ASP.NET Core 開發人員都該知道的環境變數,非常實用!

    這個 ASPNETCORE_ENVIRONMENT 環境變數會用來幫你切換不同的環境(Environment),透過「環境」的管理,可以幫助你在執行時識別不同環境下的資訊,甚至於可以指定不同環境下的組態或應用程式邏輯。

    參見: Use multiple environments in ASP.NET Core

  2. ASPNETCORE_URLS

    我們在用 dotnet run 啟動 ASP.NET Core 在啟動的時候,會先去查找一個 Properties/launchSettings.json 檔案,找到裡面的 profiles.設定檔名稱.applicationUrl 屬性,並以這個屬性指定的 hostport 來啟動網站,其設定的格式為 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 環境變數。

  3. ASPNETCORE_Kestrel__Certificates__Default__PathASPNETCORE_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'
    
  4. ASPNETCORE_CONTENTROOT

    ASP.NET Core 在啟動的時候,預設會找主程式當前的路徑作為內容(Content)的根目錄,這裡的 Content 指的是 ASP.NET Core 應用程式部署時所有的「內容」,也就是所有的 *.dll 所在的那些資料夾內容。

    當你想在啟動應用程式的時候,選用另一個資料夾當作載入組件(assembly)的依據,你才需要指定這個 ASPNETCORE_CONTENTROOT 環境變數,基本上很少用。

  5. 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) 技術細節探索

  6. 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 這個環境變數。

  7. ASPNETCORE_PREVENTHOSTINGSTARTUP

    如果你想要在啟動時完全關閉 hosting startup assemblies 機制,就可以使用 ASPNETCORE_PREVENTHOSTINGSTARTUP 這個環境變數。

    ASPNETCORE_PREVENTHOSTINGSTARTUP=1
    
  8. 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": "*"
    }
    
  9. ASPNETCORE_SHUTDOWNTIMEOUTSECONDS

    當 ASP.NET Core 應用程式呼叫 IApplicationLifetime.ApplicationStopping 或在嘗試停止應用程式的過程,因為特定原因導致無法關閉時,可以設定等待幾秒就要強制關閉!(預設 5 秒)

    ASPNETCORE_SHUTDOWNTIMEOUTSECONDS=10
    
  10. ASPNETCORE_STARTUPASSEMBLY

    在 ASP.NET Core 5 之前都有個 Startup 類別,雖然在 ASP.NET Core 6 的 Minimal APIs 看不到了,但事實上你還是可以定義這個類別,並使用早期的 API 進行定義。如果你想將 Startup 類別寫在完全不同的另一個組件下,就可以利用 ASPNETCORE_STARTUPASSEMBLY 環境變數來動態指定啟動類別 (Startup class),非常方便!

  11. 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 LinuxWeb 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

其他可能會用到的環境變數

  • 強迫在 Console 顯示最完整的 Log 訊息

    ASPNETCORE_Logging__Console__LogLevel__Default=Trace
    

如果不想載入 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);
}

相關連結