次の方法で共有


.NET アプリ参照をコンテナー化する

このリファレンス記事では、.NET アプリをコンテナーとして発行するときに生成されるコンテナー イメージを構成する方法について説明します。 この記事では、イメージ、実行環境、およびコンテナーの起動時に実行されるコマンドを制御するために設定できるさまざまなプロパティについて説明します。

コンテナー イメージを構成する

生成されたコンテナーの多くの側面は、MSBuild プロパティを使用して制御できます。 一般に、Dockerfile でコマンドを使用していくつかの構成を設定できる場合は、MSBuild を使用して同じ操作を行うことができます。

手記

これに対する唯一の例外は、RUN コマンドです。 コンテナーの構築方法により、それらをエミュレートすることはできません。 この機能が必要な場合は、Dockerfile を使用してコンテナー イメージをビルドすることを検討してください。

.NET SDK を使用して RUN コマンドを実行する方法はありません。 これらのコマンドは、多くの場合、一部の OS パッケージをインストールしたり、新しい OS ユーザーを作成したり、任意の数のものを作成したりするために使用されます。 .NET SDK コンテナー構築機能を引き続き使用する場合は、代わりに、これらの変更を使用してカスタム基本イメージを作成してから、この基本イメージを使用できます。 詳細については、ContainerBaseImageを参照してください。

ContainerArchiveOutputPath

tar.gz アーカイブ内にコンテナー イメージを作成するには、ContainerArchiveOutputPath プロパティを使用します。 この機能は、ワークフローが単純ではなく、たとえば画像をプッシュする前にスキャン ツールを実行する必要がある場合に便利です。 アーカイブが作成されたら、アーカイブの移動、スキャン、またはローカル Docker ツールチェーンへの読み込みを行うことができます。

アーカイブに発行するには、ContainerArchiveOutputPath プロパティを dotnet publish コマンドに追加します。次に例を示します。

dotnet publish \
  -p PublishProfile=DefaultContainer \
  -p ContainerArchiveOutputPath=./images/sdk-container-demo.tar.gz

フォルダー名または特定のファイル名を持つパスを指定できます。 フォルダー名を指定すると、イメージ アーカイブ ファイルに対して生成されるファイル名は $(ContainerRepository).tar.gzという名前になります。 これらのアーカイブには、すべての ContainerImageTagsに対して 1 つのファイルが作成されるため、それらの中に複数のタグを含めることができます。

コンテナー イメージの名前付けの構成

コンテナー イメージは、特定の名前付け規則に従います。 イメージの名前は、いくつかの部分、レジストリ、オプションのポート、リポジトリ、およびオプションのタグとファミリで構成されます。

REGISTRY[:PORT]/REPOSITORY[:TAG[-FAMILY]]

たとえば、完全修飾 mcr.microsoft.com/dotnet/runtime:8.0-alpine イメージ名について考えてみます。

  • mcr.microsoft.com レジストリです (この場合は Microsoft コンテナー レジストリを表します)。
  • dotnet/runtime リポジトリです (ただし、これを user/repositoryと考える人もいます)。
  • 8.0-alpine はタグとファミリです (ファミリは、OS パッケージのあいまいさを解消するのに役立つ省略可能な指定子です)。

次のセクションで説明する一部のプロパティは、生成されたイメージ名の一部の管理に対応しています。 イメージ名とビルド プロパティの関係をマップする次の表を考えてみましょう。

イメージ名部分 MSBuild プロパティ 値の例
REGISTRY[:PORT] ContainerRegistry mcr.microsoft.com:443
PORT ContainerPort :443
REPOSITORY ContainerRepository dotnet/runtime
TAG ContainerImageTag 8.0
FAMILY ContainerFamily -alpine

次のセクションでは、生成されたコンテナー イメージを制御するために使用できるさまざまなプロパティについて説明します。

ContainerBaseImage

コンテナーの基本イメージ プロパティは、イメージの基礎として使用されるイメージを制御します。 既定では、プロジェクトのプロパティに基づいて次の値が推論されます。

  • プロジェクトが自己完結型の場合、mcr.microsoft.com/dotnet/runtime-deps イメージが基本イメージとして使用されます。
  • プロジェクトが ASP.NET Core プロジェクトの場合、mcr.microsoft.com/dotnet/aspnet イメージが基本イメージとして使用されます。
  • それ以外の場合は、mcr.microsoft.com/dotnet/runtime イメージが基本イメージとして使用されます。

画像のタグは、選択した TargetFrameworkの数値コンポーネントであると推定されます。 たとえば、net6.0 をターゲットとするプロジェクトでは、推論された基本イメージの 6.0 タグが作成され、net7.0-linux プロジェクトでは 7.0 タグが使用されます。

ここで値を設定する場合は、ベースとして使用するイメージの完全修飾名 (任意のタグを含む) を設定する必要があります。

<PropertyGroup>
    <ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:8.0</ContainerBaseImage>
</PropertyGroup>

.NET SDK バージョン 8.0.200 では、ContainerBaseImage 推論が改善され、サイズとセキュリティが最適化されます。

  • linux-musl-x64 または linux-musl-arm64 ランタイム識別子を対象とすると、プロジェクトが確実に実行されるように、alpine イメージバリアントが自動的に選択されます。
    • プロジェクトで PublishAot=true を使用する場合は、最適なサイズとセキュリティのために基本イメージの nightly/runtime-depsjammy-chiseled-aot バリアントが使用されます。
    • プロジェクトで InvariantGlobalization=false を使用する場合は、ローカライズが引き続き機能するように、-extra バリアントが使用されます。

イメージバリアントのサイズと特性の詳細については、「.NET 8.0 Container Image Size Reportを参照してください。

ContainerFamily

.NET 8 以降では、ContainerFamily MSBuild プロパティを使用して、Microsoft が提供する別のコンテナー イメージ ファミリをアプリの基本イメージとして選択できます。 この値を設定すると、選択した TFM 固有のタグの末尾にこの値が追加され、指定されたタグが変更されます。 たとえば、.NET 基本イメージの Alpine Linux バリアントを使用するには、ContainerFamilyalpineに設定できます。

<PropertyGroup>
    <ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>

上記のプロジェクト構成では、.NET 8 ターゲット アプリの 8.0-alpine の最終的なタグが生成されます。

このフィールドは自由形式であり、多くの場合、さまざまなオペレーティング システムの配布、既定のパッケージ構成、または基本イメージへの変更のその他の フレーバー を選択するために使用できます。 このフィールドは、ContainerBaseImage が設定されている場合は無視されます。 詳細については、「.NET コンテナー イメージする」を参照してください。

ContainerRuntimeIdentifier

ContainerRuntimeIdentifier プロパティは、ContainerBaseImage が複数のプラットフォームをサポートしている場合に、コンテナーの OS とアーキテクチャを指定します。 たとえば、mcr.microsoft.com/dotnet/runtime イメージでは、linux-x64linux-armlinux-arm64、および win10-x64がサポートされます。 既定では、これはコンテナーの発行時に使用される RuntimeIdentifier に設定されます。 通常、このプロパティを明示的に設定する必要はありません。代わりに、dotnet publish コマンドで -r オプションを使用します。 選択したイメージが指定した RuntimeIdentifierをサポートしていない場合、エラーはサポートされている識別子を示します。

このプロパティを使用する必要がまったくないように、ContainerBaseImage プロパティには常に、タグを含む完全修飾イメージ名を設定できます。

<PropertyGroup>
    <ContainerRuntimeIdentifier>linux-arm64</ContainerRuntimeIdentifier>
</PropertyGroup>

.NET でサポートされるランタイム識別子の詳細については、RID カタログの参照してください。

ContainerRegistry

コンテナー レジストリ プロパティは、新しく作成されたイメージがプッシュされる場所である宛先レジストリを制御します。 既定では、ローカル Docker デーモンにプッシュされますが、リモート レジストリを指定することもできます。 認証を必要とするリモート レジストリを使用する場合は、既知の docker login メカニズムを使用して認証します。 詳細については、「コンテナー レジストリへの認証 」を参照してください。 このプロパティを使用する具体的な例については、次の XML の例を考えてみましょう。

<PropertyGroup>
    <ContainerRegistry>registry.mycorp.com:1234</ContainerRegistry>
</PropertyGroup>

このツールは、Docker Registry HTTP API V2をサポートする任意のレジストリへの発行をサポートします。 これには、次のレジストリが明示的に含まれます (多くの場合、暗黙的に)。

  • Azure Container Registry の
  • Amazon Elastic Container Registry を する
  • Google Artifact Registry
  • Docker Hub の
  • GitHub パッケージ を する
  • GitLab でホストされる Container Registry を する
  • Quay.io

これらのレジストリの操作に関する注意事項については、レジストリ固有の注意事項を参照してください。

ContainerRepository

コンテナー リポジトリは、dotnet/runtimemy-appなど、イメージ自体の名前です。 既定では、プロジェクトの AssemblyName が使用されます。

<PropertyGroup>
    <ContainerRepository>my-app</ContainerRepository>
</PropertyGroup>

イメージ名は 1 つ以上のスラッシュ区切りのセグメントで構成され、それぞれ小文字の英数字、ピリオド、アンダースコア、ダッシュのみを含めることができます。先頭は文字または数字で始まる必要があります。 それ以外の文字を指定すると、エラーがスローされます。

ContainerImageTag(s)

コンテナー イメージ タグ プロパティは、イメージに対して生成されるタグを制御します。 1 つのタグを指定するには、ContainerImageTag を使用し、複数のタグには ContainerImageTagsを使用します。

大事な

ContainerImageTagsを使用すると、一意のタグごとに 1 つずつ、複数の画像が作成されます。

タグは、多くの場合、異なるバージョンのアプリを参照するために使用されますが、異なるオペレーティング システムのディストリビューションや異なる構成を参照することもできます。

.NET 8 以降では、タグが指定されていない場合、既定値は latestです。

既定値をオーバーライドするには、次のいずれかを指定します。

<PropertyGroup>
    <ContainerImageTag>1.2.3-alpha2</ContainerImageTag>
</PropertyGroup>

複数のタグを指定するには、複数の TargetFrameworksを設定するのと同様に、ContainerImageTags プロパティでセミコロンで区切られたタグのセットを使用します。

<PropertyGroup>
    <ContainerImageTags>1.2.3-alpha2;latest</ContainerImageTags>
</PropertyGroup>

タグには、最大 127 文字の英数字、ピリオド、アンダースコア、ダッシュのみを含めることができます。 英数字またはアンダースコアで始める必要があります。 その他のフォームでは、エラーがスローされます。

手記

ContainerImageTagsを使用する場合、タグは ; 文字で区切られます。 コマンド ラインから dotnet publish を呼び出す場合 (ほとんどの CI/CD 環境の場合と同様)、値を 1 つの ' で外側にラップし、内部ラップを "二重引用符 (='"tag-1;tag-2"'など) で囲む必要があります。 次の dotnet publish コマンドについて考えてみましょう。

dotnet publish -p ContainerImageTags='"1.2.3-alpha2;latest"'

これにより、my-app:1.2.3-alpha2my-app:latestの 2 つの画像が生成されます。

先端

ContainerImageTags プロパティで問題が発生した場合は、代わりに環境変数 ContainerImageTags スコープを設定することを検討してください。

$Env:ContainerImageTags='1.2.3;latest'; dotnet publish --os linux --arch x64 /t:PublishContainer

ContainerLabel

コンテナー ラベルは、メタデータ ラベルをコンテナーに追加します。 ラベルは、多くの場合、セキュリティ スキャナーやその他のインフラストラクチャ ツールで使用するバージョンとオーサリング メタデータを格納するために使用されます。 任意の数のコンテナー ラベルを指定できます。

ContainerLabel ノードには、次の 2 つの属性があります。

  • Include: ラベルのキー。
  • Value: ラベルの値 (空の場合があります)。
<ItemGroup>
    <ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>

既定で作成されるラベルの一覧については、既定のコンテナー ラベル参照してください。

コンテナーの実行を構成する

コンテナーの実行を制御するには、次の MSBuild プロパティを使用します。

ContainerWorkingDirectory

コンテナー作業ディレクトリ ノードは、他のコマンドが実行されていない場合にコマンドが実行されるコンテナーの作業ディレクトリを制御します。

既定では、/app ディレクトリの値が作業ディレクトリとして使用されます。

<PropertyGroup>
    <ContainerWorkingDirectory>/bin</ContainerWorkingDirectory>
</PropertyGroup>

ContainerPort

コンテナー ポートは、伝送制御プロトコル (TCP) またはユーザー データグラム プロトコル (UDP) ポートをコンテナーの既知のポートの一覧に追加します。 これにより、Docker などのコンテナー ランタイムは、これらのポートをホスト マシンに自動的にマップできます。 これはコンテナーのドキュメントとしてよく使用されますが、自動ポート マッピングを有効にするためにも使用できます。

ContainerPort ノードには、次の 2 つの属性があります。

  • Include: 公開するポート番号。
  • Type: 既定値は tcpで、有効な値は tcp または udpです。
<ItemGroup>
    <ContainerPort Include="80" Type="tcp" />
</ItemGroup>

.NET 8 以降では、いくつかの既知の ASP.NET 環境変数に基づいて明示的に指定されていない場合、ContainerPort が推論されます。

  • ASPNETCORE_URLS
  • ASPNETCORE_HTTP_PORTS
  • ASPNETCORE_HTTPS_PORTS

これらの環境変数が存在する場合、それらの値は解析され、TCP ポート マッピングに変換されます。 これらの環境変数は、基本イメージ (存在する場合) から、またはプロジェクトで定義されている環境変数から ContainerEnvironmentVariable 項目を介して読み取られます。 詳細については、「ContainerEnvironmentVariable 」を参照してください。

ContainerEnvironmentVariable

コンテナー環境変数ノードを使用すると、環境変数をコンテナーに追加できます。 環境変数は、コンテナー内で実行されているアプリからすぐにアクセスでき、実行中のアプリの実行時の動作を変更するためによく使用されます。

ContainerEnvironmentVariable ノードには、次の 2 つの属性があります。

  • Include: 環境変数の名前。
  • Value: 環境変数の値。
<ItemGroup>
  <ContainerEnvironmentVariable Include="LOGGER_VERBOSITY" Value="Trace" />
</ItemGroup>

詳細については、.NET 環境変数を参照してください。

手記

現在、コンテナー イメージの発行時に .NET CLI から環境変数を設定することはできません。 詳細については、GitHub .NET SDK コンテナー ビルドを参照してください。

コンテナー コマンドを構成する

既定では、コンテナー ツールは、アプリに対して生成された AppHost バイナリ (アプリで AppHost を使用している場合) または dotnet コマンドとアプリの DLL を使用してアプリを起動します。

ただし、ContainerAppCommandContainerAppCommandArgsContainerDefaultArgsContainerAppCommandInstructionの組み合わせを使用して、アプリの実行方法を制御できます。

これらの異なる構成ポイントが存在するのは、コンテナー ENTRYPOINTCOMMAND プロパティの組み合わせが異なる基本イメージが使用され、それらのすべてをサポートできるようにするためです。 既定値はほとんどのアプリで使用できる必要がありますが、アプリの起動動作をカスタマイズする場合は、次の操作を行う必要があります。

  • 実行するバイナリを特定し、ContainerAppCommand として設定する
  • アプリケーションを実行するために必要な 引数を特定し、 として設定する
  • 省略可能な 引数 (存在する場合) を特定し、ユーザーによってオーバーライドし、 として設定できます。
  • ContainerAppCommandInstructionDefaultArgs に設定する

詳細については、次の構成項目を参照してください。

ContainerAppCommand

アプリ コマンド構成項目は、アプリの論理エントリ ポイントです。 ほとんどのアプリでは、これは AppHost であり、アプリ用に生成された実行可能バイナリです。 アプリで AppHost が生成されない場合、通常、このコマンドは dotnet <your project dll>。 これらの値は、基本コンテナー内の ENTRYPOINT の後、または ENTRYPOINT が定義されていない場合に直接適用されます。

ContainerAppCommand 構成には、entrypoint コマンドで使用するコマンド、オプション、または引数を表す単一の Include プロパティがあります。

<ItemGroup Label="ContainerAppCommand Assignment">
  <!-- This is how you would start the dotnet ef tool in your container -->
  <ContainerAppCommand Include="dotnet" />
  <ContainerAppCommand Include="ef" />

  <!-- This shorthand syntax means the same thing, note the semicolon separating the tokens. -->
  <ContainerAppCommand Include="dotnet;ef" />
</ItemGroup>

ContainerAppCommandArgs

このアプリ コマンド引数構成項目は、ContainerAppCommandに適用する必要があるアプリに論理的に必要な引数を表します。 既定では、アプリには何も生成されません。 存在する場合、引数は実行時にコンテナーに適用されます。

ContainerAppCommandArgs 構成には、ContainerAppCommand コマンドに適用するオプションまたは引数を表す単一の Include プロパティがあります。

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above,
       this would be the way to force the database to update.
  -->
  <ContainerAppCommandArgs Include="database" />
  <ContainerAppCommandArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerAppCommandArgs Include="database;update" />
</ItemGroup>

ContainerDefaultArgs

この既定の引数構成項目は、アプリのユーザーがオーバーライドできる引数を表します。 これは、アプリを簡単に開始できる方法で実行する必要がある場合がある既定値を提供するのに適した方法ですが、カスタマイズは簡単です。

ContainerDefaultArgs 構成には、ContainerAppCommand コマンドに適用するオプションまたは引数を表す単一の Include プロパティがあります。

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above,
       this would be the way to force the database to update.
  -->
  <ContainerDefaultArgs Include="database" />
  <ContainerDefaultArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerDefaultArgs Include="database;update" />
</ItemGroup>

ContainerAppCommandInstruction

アプリ コマンド命令の構成は、ContainerEntrypointContainerEntrypointArgsContainerAppCommandContainerAppCommandArgs、および ContainerDefaultArgs を組み合わせて、コンテナーで実行される最終的なコマンドを形成する方法を制御するのに役立ちます。 これは、基本イメージに ENTRYPOINT が存在するかどうかによって大きく異なります。 このプロパティは、"DefaultArgs""Entrypoint"、または "None"の 3 つの値のいずれかを受け取ります。

  • Entrypoint:
    • このモードでは、エントリ ポイントは、ContainerAppCommandContainerAppCommandArgs、および ContainerDefaultArgsによって定義されます。
  • None:
    • このモードでは、エントリ ポイントは、ContainerEntrypointContainerEntrypointArgs、および ContainerDefaultArgsによって定義されます。
  • DefaultArgs:
    • これは最も複雑なモードです。ContainerEntrypoint[Args] 項目が存在しない場合は、ContainerAppCommand[Args]ContainerDefaultArgs を使用してエントリ ポイントとコマンドを作成します。 完全に制御できるように、dotnet または /usr/bin/dotnet にハードコーディングされた基本イメージの基本イメージエントリポイントはスキップされます。
    • ContainerEntrypointContainerAppCommand の両方が存在する場合は、ContainerEntrypoint がエントリ ポイントになり、ContainerAppCommand がコマンドになります。

手記

ContainerEntrypoint および ContainerEntrypointArgs 構成項目は、.NET 8 の時点で非推奨となっています。

大事な

これは、上級ユーザー向けであり、ほとんどのアプリはエントリポイントをこの程度にカスタマイズする必要はありません。 詳細およびシナリオのユース ケースを提供する場合は、「gitHub: .NET SDK コンテナービルドのディスカッション参照してください。

ContainerUser

ユーザー構成プロパティは、コンテナーを実行する既定のユーザーを制御します。 これは、多くの場合、非ルート ユーザーとしてコンテナーを実行するために使用されます。これは、セキュリティのベスト プラクティスです。 この構成に注意する必要がある制約がいくつかあります。

  • ユーザー名、Linux ユーザー ID、グループ名、Linux グループ ID、username:groupname、その他の ID バリアントなど、さまざまな形式を使用できます。
  • 指定されたユーザーまたはグループがイメージに存在するという検証はありません。
  • ユーザーを変更すると、特にファイル システムの アクセス許可などの点で、アプリの動作 変更できます。

このフィールドの既定値は、プロジェクト TFM とターゲット オペレーティング システムによって異なります。

  • .NET 8 以降を対象とし、Microsoft ランタイム イメージを使用している場合は、次のようにします。
    • Linux では、ルートレス ユーザー app が使用されます (ただし、そのユーザー ID によって参照されます)。
    • Windows では、ルートレス ユーザー ContainerUser が使用されます
  • それ以外の場合、既定の ContainerUser は使用されません
<PropertyGroup>
  <ContainerUser>my-existing-app-user</ContainerUser>
</PropertyGroup>

先端

APP_UID 環境変数は、コンテナー内のユーザー情報を設定するために使用されます。 この値は、基本イメージで定義されている環境変数 (Microsoft .NET イメージなど) から取得することも、ContainerEnvironmentVariable 構文を使用して自分で設定することもできます。

ルート ユーザーとして実行するようにアプリを構成するには、ContainerUser プロパティを rootに設定します。 プロジェクト ファイルに、次のコードを追加します。

<PropertyGroup>
  <ContainerUser>root</ContainerUser>
</PropertyGroup>

または、コマンド ラインから dotnet publish を呼び出すときに、この値を設定することもできます。

dotnet publish -p ContainerUser=root

既定のコンテナー ラベル

ラベルは、コンテナー イメージに一貫性のあるメタデータを提供するためによく使用されます。 このパッケージには、生成されたイメージの保守性を向上させるために、いくつかの既定のラベルが用意されています。

  • org.opencontainers.image.created は、DateTime.UtcNowの現在の値の ISO 8601 形式に設定されます。

詳細については、「既存のラベル インフラストラクチャの上に従来のラベルを実装する」を参照してください。

関連項目

  • dotnet 発行 を使用して .NET アプリをコンテナー化する
  • .NET コンテナー イメージ を する