dotnet publish を使用して .NET アプリをコンテナー化する

コンテナーには、変更できないインフラストラクチャになったり、移植可能なアーキテクチャを提供したり、スケーラビリティを可能にしたりといった、さまざまな特徴とベネフィットがあります。 そのイメージを使って、ローカル開発環境、プライベート クラウド、またはパブリック クラウド用にコンテナーを作成することができます。 このチュートリアルでは、dotnet publish コマンドを使用して .NET アプリケーションをコンテナー化する方法について説明します。

必須コンポーネント

次の前提条件をインストールします。

  • .NET 8+ SDK
    .NET がインストールされている場合は、dotnet --info コマンドを使用して、使用している SDK を特定します。
  • Docker Community Edition
  • .NET 7+ SDK
    .NET がインストールされている場合は、dotnet --info コマンドを使用して、使用している SDK を特定します。
  • Docker Community Edition

これらの前提条件に加えて、.NET の Worker サービスについて理解しておくことが推奨されています。

.NET アプリの作成

コンテナー化する .NET アプリが必要であるため、まずテンプレートから新しいアプリを作成します。 ターミナルを開き、作業フォルダー (sample-directory) がまだない場合は作成し、そこに移動するようにディレクトリを変更します。 作業フォルダーで次のコマンドを実行し、Worker という名前のサブディレクトリに新しいプロジェクトを作成します。

dotnet new worker -o Worker -n DotNet.ContainerImage

フォルダー ツリーは次のようになります:

📁 sample-directory
    └──📂 Worker
        ├──appsettings.Development.json
        ├──appsettings.json
        ├──DotNet.ContainerImage.csproj
        ├──Program.cs
        ├──Worker.cs
        └──📂 obj
            ├── DotNet.ContainerImage.csproj.nuget.dgspec.json
            ├── DotNet.ContainerImage.csproj.nuget.g.props
            ├── DotNet.ContainerImage.csproj.nuget.g.targets
            ├── project.assets.json
            └── project.nuget.cache

dotnet new コマンドは、Worker という名前の新しいフォルダーを作成し、実行されると 1 秒ごとにメッセージをログに記録するワーカー サービスを生成します。 ターミナル セッションから、ディレクトリを変更して Worker フォルダーに移動します。 dotnet run コマンドを使用してアプリを起動します。

dotnet run
Building...
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:00 -05:00
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: .\Worker
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:01 -05:00
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:02 -05:00
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 10/18/2022 08:56:03 -05:00
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
Attempting to cancel the build...

ワーカー テンプレートは無期限にループします。 停止するにはキャンセル コマンド Ctrl + C を使用します。

NuGet パッケージを追加する

現在、Web 以外のプロジェクトをコンテナーとして発行するには Microsoft.NET.Build.Containers NuGet パッケージが必要です。 Microsoft.NET.Build.Containers NuGet パッケージをワーカー テンプレートに追加するには、次の dotnet add package コマンドを実行します。

dotnet add package Microsoft.NET.Build.Containers

ヒント

Web アプリを構築していて、.NET SDK 7.0.300 以降を使用している場合、このパッケージは不要です。その SDK には、すぐに使用できる同じ機能が含まれています。

コンテナー イメージ名を設定する

アプリをコンテナーとして公開するときに使用できるさまざまな構成オプションがあります。

既定で、コンテナー イメージ名はプロジェクトの AssemblyName になります。 その名前がコンテナー イメージ名として無効な場合は、次のプロジェクト ファイルに示すように ContainerRepository を指定してオーバーライドできます。

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UserSecretsId>dotnet-DotNet.ContainerImage-2e40c179-a00b-4cc9-9785-54266210b7eb</UserSecretsId>
    <ContainerRepository>dotnet-worker-image</ContainerRepository>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
  </ItemGroup>
</Project>

詳細については、「ContainerRepository」を参照してください。

既定で、コンテナー イメージ名はプロジェクトの AssemblyName になります。 その名前がコンテナー イメージ名として無効な場合は、次のプロジェクト ファイルに示すように、(ContainerImageName 古い) または優先する ContainerRepository を指定してオーバーライドできます。

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UserSecretsId>dotnet-DotNet.ContainerImage-2e40c179-a00b-4cc9-9785-54266210b7eb</UserSecretsId>
    <ContainerImageName>dotnet-worker-image</ContainerImageName>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
    <PackageReference Include="Microsoft.NET.Build.Containers" Version="7.0.401" />
  </ItemGroup>
</Project>

詳細については、「ContainerImageName」を参照してください。

.NET アプリを発行する

.NET アプリをコンテナーとして公開するには、次の dotnet publish コマンドを使用します:

dotnet publish --os linux --arch x64 /t:PublishContainer -c Release

上記の .NET CLI コマンドは、アプリをコンテナーとして発行します。

  • OS として Linux をターゲットにする (--os linux)。
  • x64 アーキテクチャを指定する (--arch x64)。
  • リリース構成を使用する (-c Release)。

重要

コンテナーをローカルにビルドするには、Docker デーモンが実行されている必要があります。 アプリをコンテナーとして公開しようとしたときにそれが実行されていない場合は、次のようなエラーが発生します。

..\build\Microsoft.NET.Build.Containers.targets(66,9): error MSB4018:
   The "CreateNewImage" task failed unexpectedly. [..\Worker\DotNet.ContainerImage.csproj]

ヒント

コンテナー化するアプリの種類によっては、コマンド ライン スイッチ (オプション) が異なることがあります。 たとえば、/t:PublishContainer 引数は、Web 以外の .NET アプリ (console テンプレートや worker テンプレートなど) にのみ必要です。 Web テンプレートの場合は、/t:PublishContainer 引数を -p:PublishProfile=DefaultContainer に置き換えます。 詳細については、.NET SDK コンテナー ビルド、問題 #141 を参照してください。

このコマンドを実行すると、次のような出力が生成されます:

Determining projects to restore...
  All projects are up-to-date for restore.
  DotNet.ContainerImage -> .\Worker\bin\Release\net8.0\linux-x64\DotNet.ContainerImage.dll
  DotNet.ContainerImage -> .\Worker\bin\Release\net8.0\linux-x64\publish\
  Building image 'dotnet-worker-image' with tags latest on top of base image mcr.microsoft.com/dotnet/aspnet:8.0
  Pushed container 'dotnet-worker-image:latest' to Docker daemon
Determining projects to restore...
  All projects are up-to-date for restore.
  DotNet.ContainerImage -> .\Worker\bin\Release\net7.0\linux-x64\DotNet.ContainerImage.dll
  DotNet.ContainerImage -> .\Worker\bin\Release\net7.0\linux-x64\publish\
  Building image 'dotnet-worker-image' with tags 1.0.0 on top of base image mcr.microsoft.com/dotnet/aspnet:7.0
  Pushed container 'dotnet-worker-image:1.0.0' to Docker daemon

このコマンドは、ワーカー アプリを publish フォルダーにコンパイルし、コンテナーをローカル Docker レジストリにプッシュします。

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

生成されるコンテナーの多くの側面は、MSBuild プロパティによって制御できます。 一般に、Dockerfile でコマンドを使用して一部の構成を設定できる場合は、MSBuild を介して同じことを実行できます。

Note

この唯一の例外は RUN コマンドです。 コンテナーのビルドの方法が理由で、それらはエミュレートできません。 この機能が必要な場合は、Dockerfile を使用してコンテナー イメージをビルドする必要があります。

ContainerArchiveOutputPath

.NET 8 以降では、tar.gz アーカイブとしてコンテナーを直接作成できます。 この機能は、たとえば画像をプッシュする前にスキャン ツールを実行する必要がある場合などワークフローが複雑な場合に便利です。 アーカイブが作成されたら、アーカイブの移動、スキャン、またはローカル 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
イメージ名の部分 MSBuild のプロパティ サンプル値
REGISTRY[:PORT] ContainerRegistry mcr.microsoft.com:443
PORT ContainerPort :443
REPOSITORY ContainerImageName dotnet/runtime
TAG ContainerImageTag 8.0

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

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>
<PropertyGroup>
    <ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:7.0</ContainerBaseImage>
</PropertyGroup>

ContainerFamily

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

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

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

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

ContainerRuntimeIdentifier

コンテナー ランタイム識別子プロパティは、ContainerBaseImage が複数のプラットフォームをサポートしている場合に、コンテナーによって使用されるオペレーティング システムとアーキテクチャを制御します。 たとえば、mcr.microsoft.com/dotnet/runtime イメージは現在、同じタグを基に linux-x64linux-armlinux-arm64win10-x64 イメージのすべてをサポートしているため、それらのいずれのバージョンを使用するのかをツールに指示する手段が必要です。 既定では、コンテナーを発行したときに選択した RuntimeIdentifier の値に設定されます。 このプロパティを明示的に設定する必要はほとんどありません。その代わりに、dotnet publish コマンドに -r オプションを使用します。 選択したイメージが、選択した RuntimeIdentifier をサポートしていない場合は、イメージがサポートしている RuntimeIdentifiers が説明するエラーが発生します。

このプロパティをまったく使用しないで済むように、常に 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 をサポートするレジストリへの発行をサポートしています。 これには、次のレジストリが明示的に (おそらく、他の多くのものも暗黙的に) 含まれます。

これらのレジストリの使用に関する注意事項については、レジストリ固有の注意事項をご覧ください。

ContainerRepository

コンテナー リポジトリは、イメージ自体の名前です、(例: dotnet/runtime または my-app)。 既定で、プロジェクトの AssemblyName が使用されます。

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

ContainerImageName

コンテナー イメージ名は、イメージ自体の名前を制御します (例: dotnet/runtime または my-app)。 既定で、プロジェクトの AssemblyName が使用されます。

<PropertyGroup>
    <ContainerImageName>my-app</ContainerImageName>
</PropertyGroup>

Note

.NET 8 以降では、ContainerImageName は非推奨とされ、ContainerRepository が優先されます。

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

ContainerImageTag(s)

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

重要

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

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

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

既定で、プロジェクトの Version がタグ値として使用されます。

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

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

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

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

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

Note

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

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

これにより、次の 2 つのイメージが生成されます。my-app:1.2.3-alpha2 および my-app:latest

ヒント

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

ContainerImageTags='1.2.3;latest' dotnet publish

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 環境変数」を参照してください。

コンテナー コマンドの構成

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

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

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

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

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

ContainerAppCommand

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

ContainerAppCommand 構成には、entrypoint コマンドで使用するコマンド、オプション、または引数を表す 1 つの 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 コマンドに適用するオプションまたは引数を表す 1 つの 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 コマンドに適用するオプションまたは引数を表す 1 つの 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 によって大きく異なります。 このプロパティは、次の 3 つの値のいずれかを受け取ります: "DefaultArgs""Entrypoint" または "None"

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

Note

.NET 8 の時点で、ContainerEntrypoint 構成項目と ContainerEntrypointArgs 構成項目は非推奨になりました。

重要

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

ContainerUser

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

  • ユーザー名、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 構文を使用して自分で設定することもできます。

ただし、ContainerEntrypointContainerEntrypointArgs を使用して、アプリの実行方法を制御できます。

ContainerEntrypoint

コンテナー エントリ ポイントを使用して、コンテナーの ENTRYPOINT をカスタマイズできます。これは、コンテナーの起動時に呼び出される実行可能ファイルです。 既定では、アプリ ホストを作成するビルドの場合、それが ContainerEntrypoint として設定されます。 実行可能ファイルを作成しないビルドの場合、dotnet path/to/app.dllContainerEntrypoint として使用されます。

ContainerEntrypoint ノードには 1 つの属性があります。

  • Include: ContainerEntrypoint コマンドで使用するコマンド、オプション、または引数。

たとえば、次のサンプル .NET プロジェクト項目グループを考えます。

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

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

ContainerEntrypointArgs

コンテナー エントリ ポイント args ノードは、ContainerEntrypoint に提供される既知の引数を制御します。 これは、ContainerEntrypoint がユーザーがそのままで使用したいと考える可能性があるプログラムである場合に使用する必要があります。 既定で、ContainerEntrypointArgs は自動的に作成されません。

ContainerEntrypointArg ノードには 1 つの属性があります。

  • Include: ContainerEntrypoint コマンドに適用するオプションまたは引数。

次の .NET プロジェクト項目グループの例を考えます。

<ItemGroup>
  <!-- Assuming the ContainerEntrypoint defined above,
       this would be the way to update the database by
       default, but let the user run a different EF command. -->
  <ContainerEntrypointArgs Include="database" />
  <ContainerEntrypointArgs Include="update" />

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

既定のコンテナー ラベル

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

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

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

リソースをクリーンアップする

この記事では、.NET ワーカーをコンテナー イメージとして公開しました。 必要に応じて、このリソースを削除します。 インストールされているイメージの一覧を表示するには、docker images コマンドを使います。

docker images

次の出力例を考えてみましょう。

REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
dotnet-worker-image   1.0.0     25aeb97a2e21   12 seconds ago   191MB

ヒント

イメージ ファイルは大きくなることがあります。 普通、アプリのテスト中および開発中に作成した一時的なコンテナーは削除します。 通常、ランタイムがインストールされた基本イメージは、そのランタイムを基にして他のイメージをビルドする予定がある場合は、残しておきます。

イメージを削除するには、イメージ ID をコピーし、docker image rm コマンドを実行します。

docker image rm 25aeb97a2e21

次のステップ