.NET Coreにおける環境変数設定プロバイダの内部構造

.NET Coreの設定基盤は、複数の設定ソースからのキー・バリューペア読み込みをサポートする柔軟な仕組みです。環境変数経由の設定は、特にコンテナデプロイメントにおいて不可欠な手法となっています。本稿では、その環境変数設定プロバイダの内部実装と特殊な変換ルールを徹底解説します。

コンソールアプリケーションでの実装

まず、基本的なコンソールアプリでの使用方法を確認します。

必要となるNuGetパッケージ

<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="8.0.0" />

設定オブジェクトの構築

static void Main(string[] commandLineArgs)
{
    var builder = new ConfigurationBuilder()
        .AddCommandLine(commandLineArgs)
        .AddEnvironmentVariables()
        .Build();
    
    var redisHost = builder["Caching:Redis:Host"];
    Console.WriteLine($"Redis Host: {redisHost}");
}

ASP.NET Coreでの統合

ASP.NET Coreでは、ホストビルダーに設定機能が組み込まれています。

var webHost = WebApplication.CreateBuilder(args);
webHost.Configuration.AddEnvironmentVariables();
var app = webHost.Build();

プレフィックスを指定して環境変数をフィルタリングすることも可能です:

var customConfig = new ConfigurationBuilder()
    .AddEnvironmentVariables("MYAPP_")
    .Build();

環境変数プロバイダの仕組み

Dockerコンテナでの実践的な使用例を見てみましょう:

docker run --name my-webapi --rm -it -p 8080:80 \
  -e "Serilog__MinimumLevel__Override__Microsoft=Verbose" \
  -e "ConnectionStrings__Postgres=Host=pg-server;Database=mydb;Username=app;Password=secret" \
  sample-api:latest

この環境変数は、以下のようなJSON設定ファイルの構造に対応付けられます:

{
  "Serilog": {
    "MinimumLevel": {
      "Override": {
        "Microsoft": "Information"
      }
    }
  },
  "ConnectionStrings": {
    "Postgres": "Host=localhost;Database=test"
  }
}

二重アンダースコアの謎

環境変数「Serilog__MinimumLevel__Override__Microsoft」のように、二重アンダースコア(__)が使用される理由は、階層構造を表現するための仕様です。コロン(:)は環境変数の命名規則で問題があるため、アンダースコアが採用されています。

ソースコードを追跡すると、EnvironmentVariablesConfigurationProvider内で以下の処理が実行されます:

private Dictionary<string, string> LoadVariables()
{
    var data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
    var prefix = Prefix ?? string.Empty;
    
    foreach (DictionaryEntry envVar in Environment.GetEnvironmentVariables())
    {
        var key = envVar.Key as string;
        if (key != null && key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
        {
            var normalizedKey = ConvertDelimiter(key.Substring(prefix.Length));
            data[normalizedKey] = envVar.Value as string;
        }
    }
    
    return data;
}

キー変換処理の詳細

実際のキー変換は以下のように行われます:

private string ConvertDelimiter(string originalKey)
{
    const string delimiter = "__";
    return originalKey.Replace(delimiter, ConfigurationPath.KeyDelimiter);
}

ConfigurationPath.KeyDelimiterの値は「:」であるため、「Caching__Redis__Host」は「Caching:Redis:Host」に変換され、設定ツリーとして正しく解釈されます。

接続文字列用の特殊プレフィックス

.NET Coreは接続文字列のために専用の環境変数プレフィックスを提供しています。

プレフィックス 対象データベースプロバイダ
SQLCONNSTR_ Microsoft SQL Server
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Azure SQL Database
CUSTOMCONNSTR_ その他のカスタムプロバイダ

これらのプレフィックスを使用すると、自動的にConnectionStringsセクションに配置され、プロバイダ情報も付与されます。

環境変数キー 変換後の設定パス 自動生成されるプロバイダ情報
SQLCONNSTR_InventoryDb ConnectionStrings:InventoryDb ConnectionStrings:InventoryDb_ProviderName = System.Data.SqlClient
MYSQLCONNSTR_UserDb ConnectionStrings:UserDb ConnectionStrings:UserDb_ProviderName = MySql.Data.MySqlClient

Docker実行時の例:

docker run -d --name product-service \
  -e "SQLCONNSTR_Catalog=Server=sql2022;Database=Products;User Id=sa;Password=P@ssw0rd;" \
  -e "MYSQLCONNSTR_SessionCache=Server=cache-db;Database=sessions;Uid=app;Pwd=cache123;" \
  product-service:latest

これにより、アプリケーション内でConfiguration.GetConnectionString("Catalog")のようにして簡単に接続文字列にアクセスできます。

環境変数が設定システムに統合されるまでの全体の流れを理解することで、クラウドネイティブなアプリケーションの設定管理をより効果的に実装できます。より詳細な情報については、Microsoft公式ドキュメントをご参照ください。

タグ: dotnet-core aspnet-core configuration-provider environment-variables docker-configuration

6月14日 20:55 投稿