.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-deps
jammy-chiseled-aot
バリアントが使用されます。 - プロジェクトで
InvariantGlobalization=false
を使用する場合は、ローカライズが引き続き機能するように、-extra
バリアントが使用されます。
- プロジェクトで
イメージバリアントのサイズと特性の詳細については、「.NET 8.0 Container Image Size Report
ContainerFamily
.NET 8 以降では、ContainerFamily
MSBuild プロパティを使用して、Microsoft が提供する別のコンテナー イメージ ファミリをアプリの基本イメージとして選択できます。 この値を設定すると、選択した TFM 固有のタグの末尾にこの値が追加され、指定されたタグが変更されます。 たとえば、.NET 基本イメージの Alpine Linux バリアントを使用するには、ContainerFamily
を alpine
に設定できます。
<PropertyGroup>
<ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>
上記のプロジェクト構成では、.NET 8 ターゲット アプリの 8.0-alpine
の最終的なタグが生成されます。
このフィールドは自由形式であり、多くの場合、さまざまなオペレーティング システムの配布、既定のパッケージ構成、または基本イメージへの変更のその他の フレーバー を選択するために使用できます。 このフィールドは、ContainerBaseImage
が設定されている場合は無視されます。 詳細については、「.NET コンテナー イメージ
ContainerRuntimeIdentifier
ContainerRuntimeIdentifier
プロパティは、ContainerBaseImage
が複数のプラットフォームをサポートしている場合に、コンテナーの OS とアーキテクチャを指定します。 たとえば、mcr.microsoft.com/dotnet/runtime
イメージでは、linux-x64
、linux-arm
、linux-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/runtime
や my-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-alpha2
と my-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 を使用してアプリを起動します。
ただし、ContainerAppCommand
、ContainerAppCommandArgs
、ContainerDefaultArgs
、ContainerAppCommandInstruction
の組み合わせを使用して、アプリの実行方法を制御できます。
これらの異なる構成ポイントが存在するのは、コンテナー ENTRYPOINT
と COMMAND
プロパティの組み合わせが異なる基本イメージが使用され、それらのすべてをサポートできるようにするためです。 既定値はほとんどのアプリで使用できる必要がありますが、アプリの起動動作をカスタマイズする場合は、次の操作を行う必要があります。
- 実行するバイナリを特定し、
ContainerAppCommand
として設定する - アプリケーションを実行するために必要な
引数を特定し、 として設定する - 省略可能な
引数 (存在する場合) を特定し、ユーザーによってオーバーライドし、 として設定できます。 -
ContainerAppCommandInstruction
をDefaultArgs
に設定する
詳細については、次の構成項目を参照してください。
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
アプリ コマンド命令の構成は、ContainerEntrypoint
、ContainerEntrypointArgs
、ContainerAppCommand
、ContainerAppCommandArgs
、および ContainerDefaultArgs
を組み合わせて、コンテナーで実行される最終的なコマンドを形成する方法を制御するのに役立ちます。 これは、基本イメージに ENTRYPOINT
が存在するかどうかによって大きく異なります。 このプロパティは、"DefaultArgs"
、"Entrypoint"
、または "None"
の 3 つの値のいずれかを受け取ります。
-
Entrypoint
:- このモードでは、エントリ ポイントは、
ContainerAppCommand
、ContainerAppCommandArgs
、およびContainerDefaultArgs
によって定義されます。
- このモードでは、エントリ ポイントは、
-
None
:- このモードでは、エントリ ポイントは、
ContainerEntrypoint
、ContainerEntrypointArgs
、およびContainerDefaultArgs
によって定義されます。
- このモードでは、エントリ ポイントは、
-
DefaultArgs
:- これは最も複雑なモードです。
ContainerEntrypoint[Args]
項目が存在しない場合は、ContainerAppCommand[Args]
とContainerDefaultArgs
を使用してエントリ ポイントとコマンドを作成します。 完全に制御できるように、dotnet
または/usr/bin/dotnet
にハードコーディングされた基本イメージの基本イメージエントリポイントはスキップされます。 -
ContainerEntrypoint
とContainerAppCommand
の両方が存在する場合は、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
が使用されます
- Linux では、ルートレス ユーザー
- それ以外の場合、既定の
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 コンテナー イメージ を
する
.NET