次の方法で共有


Docker のデプロイ

ヒント

Docker または Orleansに慣れている場合でも、既知の回避策に関する潜在的な問題を回避するために、この記事を最後まで読むことをお勧めします。

この記事とそのサンプルは進行中の作業です。 フィードバック、PR、または提案を歓迎します。

Orleans ソリューションを Docker にデプロイする

Docker への Orleans のデプロイは、Docker オーケストレーターとクラスタリング スタックの設計により、難しい場合があります。 最も複雑な部分は、Docker Swarm からの オーバーレイ ネットワーク と Kubernetes ネットワーク モデルの概念を理解することです。

Docker コンテナーとネットワーク モデルは、主にステートレスコンテナーと不変コンテナーを実行するように設計されました。 Node.js または Nginx アプリケーションを実行しているクラスターの作成は非常に簡単です。 ただし、真にクラスター化されたアプリケーションや分散アプリケーション ( Orleans に基づくアプリケーションなど) など、より複雑なものを使用すると、セットアップの困難が生じる可能性があります。 これは可能ですが、Web ベースのアプリケーションをデプロイするほど簡単ではありません。

Docker クラスタリングでは、複数のホストをグループ化して 1 つのリソース プールとして機能し、 コンテナー オーケストレーターを使用して管理します。 Docker Inc.Swarm をオプションとして提供し、 Google では Kubernetes ( K8s とも呼ばれます) を提供しています。 DC/OSMesos などの他のオーケストレーターが存在しますが、このドキュメントでは Swarm と K8 が広く使用されているため、重点的に説明します。

サポートされている任意の場所で実行されるのと同じグレイン インターフェイスと実装 Orleans Docker コンテナーでも実行されます。 Docker コンテナーで Orleans アプリケーションを実行するために特別な考慮事項は必要ありません。

ここで説明する概念は、 Orleansの .NET Core バージョンと .NET Framework 4.6.1 バージョンの両方に適用されます。 ただし、Docker と .NET Core のクロスプラットフォームの性質を示すために、.NET Core を使用する例に重点を置きます。 プラットフォーム固有の詳細 (Windows/Linux/macOS) は、必要に応じて提供される場合があります。

必須コンポーネント

この記事では、次の前提条件がインストールされていることを前提としています。

  • Docker: Docker4X には、サポートされている主要なプラットフォーム用の使いやすいインストーラーがあります。 Docker エンジンと Docker Swarm が含まれています。
  • Kubernetes (K8s):Google のコンテナー オーケストレーション サービス。 これには、 Minikube (ローカル K8s デプロイ) と kubectl を依存関係と共にインストールするためのガイダンスが含まれています。
  • .NET: .NET のクロスプラットフォーム フレーバー。
  • Visual Studio Code (VSCode):任意の優先 IDE を使用できます。 VSCode はクロスプラットフォームであるため、ここでは VSCode が使用され、すべてのプラットフォームで例が動作します。 VSCode をインストールしたら、 C# 拡張機能をインストールします。

重要

Kubernetes を使用しない場合、Kubernetes のインストールは必要ありません。 Docker4X インストーラーには Swarm が既に含まれているため、Swarm に追加のインストールは必要ありません。

注意

Windows では、Docker インストーラーによってインストール中に Hyper-V が有効になります。 この記事とその例では .NET Core を使用しているため、使用されるコンテナー イメージは Windows Server NanoServer に基づいています。 代わりに .NET Framework 4.6.1 を使用する場合は、 Windows Server Core と Orleans バージョン 1.4 以降 (.NET Framework のみをサポート) に基づくイメージを使用します。

Orleans ソリューションを作成する

次の手順では、Orleans ツールを使用して標準のdotnet ソリューションを作成する方法を示します。

プラットフォームに合わせてコマンドを調整します。 ディレクトリ構造は単なる提案です。必要に応じて調整します。

mkdir Orleans-Docker
cd Orleans-Docker
dotnet new sln
mkdir -p src/OrleansSilo
mkdir -p src/OrleansClient
mkdir -p src/OrleansGrains
mkdir -p src/OrleansGrainInterfaces
dotnet new console -o src/OrleansSilo --framework netcoreapp1.1
dotnet new console -o src/OrleansClient --framework netcoreapp1.1
dotnet new classlib -o src/OrleansGrains --framework netstandard1.5
dotnet new classlib -o src/OrleansGrainInterfaces --framework netstandard1.5
dotnet sln add src/OrleansSilo/OrleansSilo.csproj
dotnet sln add src/OrleansClient/OrleansClient.csproj
dotnet sln add src/OrleansGrains/OrleansGrains.csproj
dotnet sln add src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj
dotnet add src/OrleansClient/OrleansClient.csproj reference src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj
dotnet add src/OrleansSilo/OrleansSilo.csproj reference src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj
dotnet add src/OrleansGrains/OrleansGrains.csproj reference src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj
dotnet add src/OrleansSilo/OrleansSilo.csproj reference src/OrleansGrains/OrleansGrains.csproj

これまでは、ソリューション構造とプロジェクトの定型コードのみが作成され、それらの間に参照が追加されました。 これは、通常の Orleans プロジェクトを設定するのと同じ違いはありません。

この記事の執筆時点では、 Orleans 2.0 (.NET Core とクロスプラットフォーム開発をサポート) はテクノロジ プレビュー段階でした。 その NuGet パッケージは、公式の NuGet.org フィードではなく、MyGet フィードでホストされていました。 プレビュー NuGet パッケージをインストールするには、 dotnet CLI を使用して、MyGet からソース フィードとバージョンを強制します。

dotnet add src/OrleansClient/OrleansClient.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet add src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet add src/OrleansGrains/OrleansGrains.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet add src/OrleansSilo/OrleansSilo.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet add src/OrleansSilo/OrleansSilo.csproj package Microsoft.Orleans.OrleansRuntime -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet restore

これで、単純な Orleans アプリケーションを実行するための基本的な依存関係がすべて整いました。 通常の Orleans アプリケーションのセットアップからこの時点まで何も変更されていないことに注意してください。 次に、コードを追加して機能させてみましょう。

Orleans アプリケーションを実装する

VSCode が使用されていると仮定して、ソリューション ディレクトリからcode .実行します。 このコマンドは、 VSCode でディレクトリを開き、ソリューションを読み込みます。

これは、前に作成したソリューション構造です。

Visual Studio Code: Program.cs が選択されたエクスプローラー。

Program.csOrleansHostWrapper.csIGreetingGrain.csおよびGreetingGrain.cs ファイルも、それぞれインターフェイスおよびグレイン プロジェクトに追加されました。 これらのファイルのコードを次に示します。

IGreetingGrain.cs:

using System;
using System.Threading.Tasks;
using Orleans;

namespace OrleansGrainInterfaces
{
    public interface IGreetingGrain : IGrainWithGuidKey
    {
        Task<string> SayHello(string name);
    }
}

GreetingGrain.cs:

using System;
using System.Threading.Tasks;
using OrleansGrainInterfaces;

namespace OrleansGrains
{
    public class GreetingGrain : Grain, IGreetingGrain
    {
        public Task<string> SayHello(string name)
        {
            return Task.FromResult($"Hello from Orleans, {name}");
        }
    }
}

OrleansHostWrapper.cs:

using System;
using System.NET;
using Orleans.Runtime;
using Orleans.Runtime.Configuration;
using Orleans.Runtime.Host;

namespace OrleansSilo;

public class OrleansHostWrapper
{
    private readonly SiloHost _siloHost;

    public OrleansHostWrapper(ClusterConfiguration config)
    {
        _siloHost = new SiloHost(Dns.GetHostName(), config);
        _siloHost.LoadOrleansConfig();
    }

    public int Run()
    {
        if (_siloHost is null)
        {
            return 1;
        }

        try
        {
            _siloHost.InitializeOrleansSilo();

            if (_siloHost.StartOrleansSilo())
            {
                Console.WriteLine(
                    $"Successfully started Orleans silo '{_siloHost.Name}' as a {_siloHost.Type} node.");
                return 0;
            }
            else
            {
                throw new OrleansException(
                    $"Failed to start Orleans silo '{_siloHost.Name}' as a {_siloHost.Type} node.");
            }
        }
        catch (Exception exc)
        {
            _siloHost.ReportStartupError(exc);
            Console.Error.WriteLine(exc);

            return 1;
        }
    }

    public int Stop()
    {
        if (_siloHost is not null)
        {
            try
            {
                _siloHost.StopOrleansSilo();
                _siloHost.Dispose();
                Console.WriteLine($"Orleans silo '{_siloHost.Name}' shutdown.");
            }
            catch (Exception exc)
            {
                siloHost.ReportStartupError(exc);
                Console.Error.WriteLine(exc);

                return 1;
            }
        }
        return 0;
    }
}

Program.cs (Siloアーキテクチャ)

using System;
using System.Collections.Generic;
using System.Linq;
using System.NET;
using System.Threading.Tasks;
using Orleans.Runtime.Configuration;

namespace OrleansSilo
{
    public class Program
    {
        private static OrleansHostWrapper s_hostWrapper;

        static async Task<int> Main(string[] args)
        {
            int exitCode = await InitializeOrleansAsync();

            Console.WriteLine("Press Enter to terminate...");
            Console.ReadLine();

            exitCode += ShutdownSilo();

            return exitCode;
        }

        private static int InitializeOrleansAsync()
        {
            var config = new ClusterConfiguration();
            config.Globals.DataConnectionString =
                "[AZURE STORAGE CONNECTION STRING HERE]";
            config.Globals.DeploymentId = "Orleans-Docker";
            config.Globals.LivenessType =
                GlobalConfiguration.LivenessProviderType.AzureTable;
            config.Globals.ReminderServiceType =
                GlobalConfiguration.ReminderServiceProviderType.AzureTable;
            config.Defaults.PropagateActivityId = true;
            config.Defaults.ProxyGatewayEndpoint =
                new IPEndPoint(IPAddress.Any, 10400);
            config.Defaults.Port = 10300;
            var ips = await Dns.GetHostAddressesAsync(Dns.GetHostName());
            config.Defaults.HostNameOrIPAddress =
                ips.FirstOrDefault()?.ToString();

            s_hostWrapper = new OrleansHostWrapper(config);
            return hostWrapper.Run();
        }

        static int ShutdownSilo() =>
            s_hostWrapper?.Stop() ?? 0;
    }
}

Program.cs (Client):

using System;
using System.NET;
using System.Threading;
using System.Threading.Tasks;
using Orleans;
using Orleans.Runtime.Configuration;
using OrleansGrainInterfaces;

namespace OrleansClient
{
    class Program
    {
        private static IClusterClient s_client;
        private static bool s_running;

        static async Task Main(string[] args)
        {
            await InitializeOrleansAsync();

            Console.ReadLine();

            s_running = false;
        }

        static async Task InitializeOrleansAsync()
        {
            var config = new ClientConfiguration
            {
                DeploymentId = "Orleans-Docker";
                PropagateActivityId = true;
            };
            var hostEntry =
                await Dns.GetHostEntryAsync("orleans-silo");
            var ip = hostEntry.AddressList[0];
            config.Gateways.Add(new IPEndPoint(ip, 10400));

            Console.WriteLine("Initializing...");

            using client = new ClientBuilder().UseConfiguration(config).Build();
            await client.Connect();
            s_running = true;
            Console.WriteLine("Initialized!");

            var grain = client.GetGrain<IGreetingGrain>(Guid.Empty);

            while (s_running)
            {
                var response = await grain.SayHello("Gutemberg");
                Console.WriteLine($"[{DateTime.UtcNow}] - {response}");

                await Task.Delay(1000);
            }
        }
    }
}

グレイン実装の詳細については、この記事の範囲外であるため、ここでは説明しません。 詳細については、その他の関連ドキュメントを参照してください。 これらのファイルは最小限の Orleans アプリケーションを表しており、この記事の残りの部分の開始点として機能します。

この記事では、 OrleansAzureUtils メンバーシップ プロバイダーを使用しますが、他の Orleansサポートされているプロバイダーを使用できます。

Dockerfile

Docker はイメージを使用してコンテナーを作成します。 カスタム イメージの作成の詳細については、 Docker のドキュメントを参照してください。 この記事では、Microsoft の公式 イメージを使用します。 ターゲットプラットフォームと開発プラットフォームに基づいて、適切なイメージを選択します。 microsoft/dotnet:1.1.2-sdkここでは、Linux ベースのイメージを使用します。 Windows の場合、たとえば、 microsoft/dotnet:1.1.2-sdk-nanoserver を使用できます。 ニーズに合ったものを選択します。

Windows ユーザー向け注: 前述のように、クロスプラットフォームの互換性を維持するために、この記事では .NET Core と Orleans Technical Preview 2.0 を使用します。 完全にリリースされた Orleans 1.4 以降で Windows 上の Docker を使用するには、NanoServer および Linux ベースのイメージは .NET Core のみをサポートするため、Windows Server Core に基づくイメージを使用します。

Dockerfile.debug:

FROM microsoft/dotnet:1.1.2-sdk
ENV NUGET_XMLDOC_MODE skip
WORKDIR /vsdbg
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        unzip \
    && rm -rf /var/lib/apt/lists/* \
    && curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v latest -l /vsdbg
WORKDIR /app
ENTRYPOINT ["tail", "-f", "/dev/null"]

この Dockerfile は基本的に VSdbg デバッガーをダウンロードしてインストールし、空のコンテナーを起動します。コンテナーは無期限に維持されるため、デバッグ中に破棄して繰り返し起動する必要はありません。

運用環境では、イメージには SDK 全体ではなく .NET Core ランタイムのみが含まれているため、サイズが小さくなります。 Dockerfile も簡単です。

Dockerfile:

FROM microsoft/dotnet:1.1.2-runtime
WORKDIR /app
ENTRYPOINT ["dotnet", "OrleansSilo.dll"]
COPY . /app

docker-compose ファイル

docker-compose.yml ファイルは、サービス レベルでプロジェクト内の一連のサービスとその依存関係を定義します。 各サービスには、Dockerfile で選択されたイメージに基づいて、特定のコンテナーの 1 つ以上のインスタンスが含まれます。 docker-composeの詳細については、docker-compose のドキュメントを参照してください

Orleans展開の一般的なユース ケースには、docker-compose.yml サイロ用と Orleans クライアント用の 2 つのサービスを含むOrleans ファイルが含まれます。 クライアント サービスは Silo サービスに依存します。つまり、Silo サービスの実行後にのみ開始されます。 別のシナリオとして、ストレージまたはデータベース サービス/コンテナー (SQL Server など) を追加する必要があります。これは、クライアントとサイロの両方の前に開始する必要があります。 この場合、クライアント サービスとサイロ サービスの両方がデータベース サービスに依存します。

注意

先に進む前に、 ファイルではインデントdocker-composeであることに注意してください。 問題が発生した場合は、それに注意してください。

この記事では、サービスの説明方法を次に示します。

docker-compose.override.yml (デバッグ):

version: '3.1'

services:
  orleans-client:
    image: orleans-client:debug
    build:
      context: ./src/OrleansClient/bin/PublishOutput/
      dockerfile: Dockerfile.Debug
    volumes:
      - ./src/OrleansClient/bin/PublishOutput/:/app
      - ~/.nuget/packages:/root/.nuget/packages:ro
    depends_on:
      - orleans-silo
  orleans-silo:
    image: orleans-silo:debug
    build:
      context: ./src/OrleansSilo/bin/PublishOutput/
      dockerfile: Dockerfile.Debug
    volumes:
      - ./src/OrleansSilo/bin/PublishOutput/:/app
      - ~/.nuget/packages:/root/.nuget/packages:ro

docker-compose.yml (運用環境):

version: '3.1'

services:
  orleans-client:
    image: orleans-client
    depends_on:
      - orleans-silo
  orleans-silo:
    image: orleans-silo

運用環境では、ローカル ディレクトリはマップされず、 build: アクションも含まれません。 その理由は、運用環境では、イメージをビルドしてプライベート Docker レジストリにプッシュする必要があるということです。

すべてをまとめる

必要なすべてのコンポーネントの準備ができたので、それらをまとめ、Docker 内で Orleans ソリューションを実行してみましょう。

重要

次のコマンドは、ソリューション ディレクトリから実行される必要があります。

まず、ソリューションのすべての NuGet パッケージが復元されていることを確認します。 これは通常、パッケージの依存関係が変更されない限り、1 回だけ実行する必要があります。

dotnet restore

次に、通常どおり dotnet CLI を使用してソリューションをビルドし、出力ディレクトリに発行します。

dotnet publish -o ./bin/PublishOutput

ヒント

publishは、buildで動的に読み込まれたアセンブリの問題を回避するために、Orleansの代わりにここで使用されます。 より良い解決策がまだ求められています。

アプリケーションをビルドして発行した後、Dockerfile を使用して Docker イメージをビルドします。 通常、この手順では、プロジェクトごとに 1 回だけ実行する必要があります。 必要なのは、Dockerfile または docker-compose ファイルが変更された場合、または何らかの理由でローカル イメージ レジストリがクリーンアップされた場合のみです。

docker-compose build

Dockerfiledocker-compose.ymlの両方で使用されるすべての基本イメージは、レジストリからプルされ、開発用コンピューターにキャッシュされます。 アプリケーション イメージがビルドされ、すべてが実行できる状態になります。

それでは、アプリケーションを実行しましょう。

# docker-compose up -d
Creating network "orleansdocker_default" with the default driver
Creating orleansdocker_orleans-silo_1 ...
Creating orleansdocker_orleans-silo_1 ... done
Creating orleansdocker_orleans-client_1 ...
Creating orleansdocker_orleans-client_1 ... done
#

次に、 docker-compose ps を実行すると、 orleansdocker プロジェクトで実行されている 2 つのコンテナーが表示されます。

# docker-compose ps
             Name                     Command        State   Ports
------------------------------------------------------------------
orleansdocker_orleans-client_1   tail -f /dev/null   Up
orleansdocker_orleans-silo_1     tail -f /dev/null   Up

注意

Windows とコンテナーで Windows 基本イメージを使用している場合、[ コマンド ] 列には、*NIX システムで tail する PowerShell と同等のコマンドが表示され、コンテナーも同様に実行されます。

コンテナーが実行されたので、 Orleans アプリケーションを起動する必要があるたびに、コンテナーを停止する必要はありません。 コンテナー内のアプリケーションをデバッグするために IDE を統合するだけです。これは、以前は docker-compose.yml でマップされていました。

スケーリング

作成プロジェクトが実行されたら、 docker-compose scale コマンドを使用してアプリケーションを簡単にスケールアップまたはスケールダウンします。

# docker-compose scale orleans-silo=15
Starting orleansdocker_orleans-silo_1 ... done
Creating orleansdocker_orleans-silo_2 ...
Creating orleansdocker_orleans-silo_3 ...
Creating orleansdocker_orleans-silo_4 ...
Creating orleansdocker_orleans-silo_5 ...
Creating orleansdocker_orleans-silo_6 ...
Creating orleansdocker_orleans-silo_7 ...
Creating orleansdocker_orleans-silo_8 ...
Creating orleansdocker_orleans-silo_9 ...
Creating orleansdocker_orleans-silo_10 ...
Creating orleansdocker_orleans-silo_11 ...
Creating orleansdocker_orleans-silo_12 ...
Creating orleansdocker_orleans-silo_13 ...
Creating orleansdocker_orleans-silo_14 ...
Creating orleansdocker_orleans-silo_15 ...
Creating orleansdocker_orleans-silo_6
Creating orleansdocker_orleans-silo_5
Creating orleansdocker_orleans-silo_3
Creating orleansdocker_orleans-silo_2
Creating orleansdocker_orleans-silo_4
Creating orleansdocker_orleans-silo_9
Creating orleansdocker_orleans-silo_7
Creating orleansdocker_orleans-silo_8
Creating orleansdocker_orleans-silo_10
Creating orleansdocker_orleans-silo_11
Creating orleansdocker_orleans-silo_15
Creating orleansdocker_orleans-silo_12
Creating orleansdocker_orleans-silo_14
Creating orleansdocker_orleans-silo_13

数秒後、サービスは要求された特定の数のインスタンスにスケーリングされます。

# docker-compose ps
             Name                     Command        State   Ports
------------------------------------------------------------------
orleansdocker_orleans-client_1   tail -f /dev/null   Up
orleansdocker_orleans-silo_1     tail -f /dev/null   Up
orleansdocker_orleans-silo_10    tail -f /dev/null   Up
orleansdocker_orleans-silo_11    tail -f /dev/null   Up
orleansdocker_orleans-silo_12    tail -f /dev/null   Up
orleansdocker_orleans-silo_13    tail -f /dev/null   Up
orleansdocker_orleans-silo_14    tail -f /dev/null   Up
orleansdocker_orleans-silo_15    tail -f /dev/null   Up
orleansdocker_orleans-silo_2     tail -f /dev/null   Up
orleansdocker_orleans-silo_3     tail -f /dev/null   Up
orleansdocker_orleans-silo_4     tail -f /dev/null   Up
orleansdocker_orleans-silo_5     tail -f /dev/null   Up
orleansdocker_orleans-silo_6     tail -f /dev/null   Up
orleansdocker_orleans-silo_7     tail -f /dev/null   Up
orleansdocker_orleans-silo_8     tail -f /dev/null   Up
orleansdocker_orleans-silo_9     tail -f /dev/null   Up

重要

これらの例の Command 列は、デバッガー コンテナーが使用されているため、 tail コマンドを示しています。 運用環境では、たとえば dotnet OrleansSilo.dllが表示されます。

Docker Swarm

Docker のクラスタリング スタックは Swarm と呼ばれます。 詳細については、「 Docker Swarm」を参照してください。

この記事で説明するアプリケーションを Swarm クラスターで実行するには、追加の作業は必要ありません。 docker-compose up -d ノードでSwarmを実行すると、構成された規則に基づいてコンテナーがスケジュールされます。 同じことが、 Azure Kubernetes Service (AKS) ( Swarm モード) や AWS Elastic Container Service (ECS) などの他の Swarm ベースのサービスにも適用されます。 Swarm アプリケーションをデプロイする前に、Orleans クラスターをデプロイするだけです。

注意

stackdeploycompose v3 をサポートする Swarm モードで Docker エンジンを使用する場合は、ソリューションをデプロイするためのより優れた方法がdocker stack deploy -c docker-compose.yml <name>。 これには、Docker エンジンと互換性のある v3 compose ファイルが必要であることに注意してください。 Azure や AWS などの多くのホステッド サービスでは、引き続き v2 と古いエンジンが使用されています。

Google Kubernetes (K8s)

Kubernetes を使用してOrleansをホストすることを計画している場合は、コミュニティが管理するクラスタリング プロバイダーを OrleansContrib\Orleans で使用できます。Clustering.Kubernetes。 そこでは、プロバイダーを使用して Kubernetes で Orleans をシームレスにホストする方法に関するドキュメントとサンプルを見つけます。

コンテナー内の Orleans をデバッグする

コンテナーで Orleans をゼロから実行することが理解されたので、Docker の最も重要な原則の 1 つである不変性を活用することが有益です。 コンテナーには、運用環境と同じイメージ、依存関係、および開発中のランタイムが必要です。 この方法は、従来の "自分のコンピューターで動作します" という問題を防ぐのに役立ちます。 これを可能にするには、コンテナー 内で 実行されているアプリケーションにデバッガーをアタッチするなど、コンテナー内で開発する方法が必要です。

さまざまなツールを使用してこれを実現するには、複数の方法があります。 執筆時点で複数のオプションを評価した後、アプリケーションに対するより単純で侵入が少ないと思われるオプションが選択されました。

前述のように、 VSCode を使用してサンプルを開発します。 コンテナー内の Orleans アプリケーションにデバッガーをアタッチする方法を次に示します。

まず、ソリューション内の .vscode ディレクトリ内の 2 つのファイルを変更します。

tasks.json:

{
    "version": "0.1.0",
    "command": "dotnet",
    "isShellCommand": true,
    "args": [],
    "tasks": [
        {
            "taskName": "publish",
            "args": [
                "${workspaceRoot}/Orleans-Docker.sln", "-c", "Debug", "-o", "./bin/PublishOutput"
            ],
            "isBuildCommand": true,
            "problemMatcher": "$msCompile"
        }
    ]
}

このファイルは、基本的に、プロジェクトがビルドされるたびに、VSCode コマンドを実行することをpublishに示します。これは、以前に手動で行った方法と同様です。

launch.json:

{
   "version": "0.2.0",
   "configurations": [
        {
            "name": "Silo",
            "type": "coreclr",
            "request": "launch",
            "cwd": "/app",
            "program": "/app/OrleansSilo.dll",
            "sourceFileMap": {
                "/app": "${workspaceRoot}/src/OrleansSilo"
            },
            "pipeTransport": {
                "debuggerPath": "/vsdbg/vsdbg",
                "pipeProgram": "/bin/bash",
                "pipeCwd": "${workspaceRoot}",
                "pipeArgs": [
                    "-c",
                    "docker exec -i orleansdocker_orleans-silo_1 /vsdbg/vsdbg --interpreter=vscode"
                ]
            }
        },
        {
            "name": "Client",
            "type": "coreclr",
            "request": "launch",
            "cwd": "/app",
            "program": "/app/OrleansClient.dll",
            "sourceFileMap": {
                "/app": "${workspaceRoot}/src/OrleansClient"
            },
            "pipeTransport": {
                "debuggerPath": "/vsdbg/vsdbg",
                "pipeProgram": "/bin/bash",
                "pipeCwd": "${workspaceRoot}",
                "pipeArgs": [
                    "-c",
                    "docker exec -i orleansdocker_orleans-client_1 /vsdbg/vsdbg --interpreter=vscode"
                ]
            }
        }
    ]
}

次に、 VSCode (発行も行う) からソリューションをビルドし、Silo 構成とクライアント構成の両方を開始します。 VSCode は、実行中の docker exec サービス インスタンス/コンテナーに docker-compose コマンドを送信して、アプリケーションにアタッチされたデバッガーを起動します。 それです! デバッガーはコンテナーにアタッチされ、ローカルで実行されている Orleans アプリケーションのデバッグと同様に使用できます。 主な違いは、アプリケーションがコンテナー内で実行されていることです。 開発が完了したら、コンテナー イメージをレジストリに発行し、運用環境の Docker ホストにプルします。