Развертывание Docker

Совет

Даже если вы очень знакомы с Docker и/или Orleans, как и любая другая Orleans документация, рекомендуется прочитать его до конца, чтобы избежать проблем, с которыми мы уже работали.

Эта статья и ее пример являются работой, выполняющейся. Любой отзыв, PR или предложение очень добро пожаловать.

Развертывание Orleans решений в Docker

Развертывание в Docker может быть сложно, учитывая Orleans способ разработки оркестраторов Docker и кластеризация стеков. Самое сложное заключается в том, чтобы понять концепцию наложения сети из Модели сети Docker Swarm и Kubernetes.

Контейнеры Docker и сетевые модели предназначены для запуска в основном бессерверных и неизменяемых контейнеров. Таким образом, создание кластера под управлением node.js или приложений Nginx довольно просто. Однако если вы попытаетесь использовать что-то более сложное, например реальное кластеризованное или распределенное приложение (например Orleans, на основе), у вас в конечном итоге возникнут проблемы с настройкой. Это возможно, но не так просто, как веб-приложения.

Docker кластеризация состоит из объединения нескольких узлов для работы в качестве одного пула ресурсов, управляемого с помощью оркестратора контейнеров. Docker Inc. предоставьте Swarm в качестве варианта оркестрации контейнеров, а Google имеет Kubernetes (aka K8s). Существуют другие оркестраторы, такие как DC/OS, Mesos, но в этом документе мы поговорим о Swarm и K8s, как они более широко используются.

Те же интерфейсы и реализация, которые выполняются в любом месте Orleans , уже поддерживаются в контейнерах Docker. Для запуска приложения в контейнерах Docker не требуются особые рекомендации.

Основные понятия, описанные здесь, можно использовать как в .NET Core, так и в . Orleans NET 4.6.1, но для иллюстрации кроссплатформенного характера Docker и .NET Core, мы сосредоточимся на примере, учитывая, что вы используете .NET Core. Сведения о платформе (Windows/Linux/OSX) можно указать в этой статье.

Необходимые компоненты

В этой статье предполагается, что установлены следующие предварительные требования:

  • Docker — Docker4X имеет простой установщик для основных поддерживаемых платформ. Он содержит подсистему Docker и Docker Swarm.
  • Kubernetes (K8s) — предложение Google для оркестрации контейнеров. Он содержит рекомендации по установке Minikube (локальное развертывание K8s) и kubectl вместе со всеми его зависимостями.
  • .NET — кроссплатформенный вкус .NET
  • Visual Studio Code (VSCode) — вы можете использовать любую нужную интегрированную среду разработки. VSCode является кроссплатформенным, поэтому мы используем его для обеспечения работы на всех платформах. После установки VSCode установите расширение C#.

Внимание

Если вы не собираетесь использовать kubernetes, вам не требуется. Установщик Docker4X уже включает Swarm, поэтому для его использования не требуется дополнительная установка.

Примечание.

В Windows установщик Docker включает Hyper-V в процессе установки. Так как в этой статье и его примерах используется .NET Core, используемые образы контейнеров основаны на Windows Server NanoServer. Если вы не планируете использовать .NET Core и будете использовать полную платформу .NET 4.6.1, образ должен быть Windows Server Core и версия Orleans 1.4+ (которая поддерживает только полную платформу .NET).

Создание решения 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 проект.

К тому времени, когда эта статья была написана, 2.0 (которая является единственной версией, поддерживающей .NET Core и кроссплатформенной) находится в Версии технологий, Orleans поэтому его пакеты NuGet размещаются в веб-канале MyGet и не публикуются в Nuget.org официальный веб-канал. Чтобы установить пакеты NuGet предварительной версии, мы будем использовать dotnet интерфейс командной строки, заставляющий исходный веб-канал и версию из 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: Explorer with Program.cs selected.

Мы также добавили Program.cs, OrleansHostWrapper.cs, IGreetingGrain.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 (клиент):

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/dotnet:1.1.2-sdk образ под управлением Linux. Например, можно использовать microsoft/dotnet:1.1.2-sdk-nanoserver для Windows. Выберите тот, который соответствует вашим потребностям.

Примечание для пользователей Windows: как ранее упоминание, чтобы быть кроссплатформенными, мы используем .NET Core и Orleans Technical preview 2.0 в этой статье. Если вы хотите использовать Docker в Windows с полностью выпущенным Orleans 1.4+, необходимо использовать образы, основанные на Windows Server Core, так как образы NanoServer и Linux поддерживают только .NET 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 и запускает пустой контейнер, сохраняя его в живых навсегда, чтобы мы не должны отключать или отладить во время отладки.

Теперь для рабочей среды образ меньше, так как он содержит только среду выполнения .NET Core, а не весь пакет SDK, а dockerfile немного проще:

Dockerfile:

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

Файл docker-compose

Файл docker-compose.yml , по сути, определяет (в проекте) набор служб и его зависимостей на уровне обслуживания. Каждая служба содержит один или несколько экземпляров заданного контейнера, который основан на образах, выбранных в Dockerfile. Дополнительные сведения см docker-compose . в документации по docker-compose.

Orleans Для развертывания распространенный вариант использования заключается в наличии docker-compose.yml двух служб. Один для Silo, а другой для OrleansOrleans клиента. Клиент будет иметь зависимость от 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.

Итоговое объединение

Теперь у нас есть все движущиеся части, необходимые для запуска приложения Orleans , мы собираемся объединить его, чтобы мы могли запустить наше Orleans решение внутри Docker (Наконец!).

Внимание

Следующие команды должны выполняться из каталога решения.

Во-первых, давайте восстановите все пакеты NuGet из нашего решения. Это нужно сделать только один раз. Это необходимо сделать только при изменении зависимости пакета от проекта.

dotnet restore

Теперь давайте создадим наше решение с помощью dotnet интерфейса командной строки как обычно и опубликуем его в выходной каталог:

dotnet publish -o ./bin/PublishOutput

Совет

Мы используем publish здесь вместо сборки, чтобы избежать проблем с динамически загруженными сборками.Orleans Мы по-прежнему ищем лучшее решение для него.

С помощью приложения, созданного и опубликованного, необходимо создать образы Dockerfile. Этот шаг требуется выполнить только один раз для каждого проекта и выполняться повторно, если изменить Dockerfile, docker-compose или по какой-либо причине вы очистили локальный реестр образов.

docker-compose build

Все образы, используемые как в Dockerfile реестре, так и docker-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вы увидите 2 контейнера, запущенных для orleansdocker проекта:

# 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 в качестве базы, столбец "Команда" покажет вам относительную команду tail PowerShell в системах *NIX, чтобы контейнер был таким же образом.

Теперь, когда у вас есть контейнеры, вам не нужно останавливать его каждый раз, когда вы хотите запустить Orleans приложение. Все, что вам нужно, — интегрировать интегрированную среду разработки для отладки приложения в контейнере, который ранее был сопоставлен в вашей 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 узле контейнеры будут запланированы на основе настроенных правил. Это же относится к другим службам на основе Swarm, таким как Docker Datacenter, Azure ACS (в режиме Swarm) и службе контейнеров AWS ECS. Все, что необходимо сделать, заключается в развертывании Swarmкластера перед развертыванием приложения dockerizedOrleans .

Примечание.

Если вы используете подсистему Docker с режимом Swarm, который уже поддерживает stack, deployи compose версии 3, лучше подходит для развертывания решения docker stack deploy -c docker-compose.yml <name>. Имейте в виду, что для поддержки подсистемы Docker и большинства размещенных служб, таких как Azure и AWS, по-прежнему используются версии 2 и более ранних версий.

Google Kubernetes (K8s)

Если вы планируете использовать Kubernetes для размещенияOrleans, существует поставщик кластеризация сообщества, доступный в OrleansContrib\Orleans. Clustering.Kubernetes и здесь можно найти документацию и примеры размещения Orleans в Kubernetes без проблем с помощью поставщика.

Отладка Orleans внутри контейнеров

Теперь, когда вы знаете, как работать Orleans в контейнере с нуля, было бы хорошо использовать один из самых важных принципов в Docker. Контейнеры неизменяемы. И они должны иметь (почти) тот же образ, зависимости и среду выполнения в разработке, что и в рабочей среде. Это гарантирует хорошую старую инструкцию "Она работает на моем компьютере!" никогда не происходит снова. Чтобы сделать это возможным, необходимо иметь способ разработки внутри контейнера и включает отладчик, подключенный к приложению внутри контейнера.

Существует несколько способов достичь этого с помощью нескольких инструментов. После оценки нескольких, к тому времени, когда я написал эту статью, я в итоге выбрать тот, который выглядит более простым и менее навязчивым в приложении.

Как упоминание ранее в этой статье, мы используем VSCode для разработки примера, поэтому здесь показано, как подключить отладчик к приложению Orleans внутри контейнера.

Сначала измените два файла в .vscode каталоге в решении:

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, так и клиент. Она отправит команду в запущенный docker execdocker-compose экземпляр или контейнер службы, чтобы запустить отладчик в приложение, и это так. У вас есть отладчик, подключенный к контейнеру, и он используется так, как если бы он был локально запущенным Orleans приложением. Разница заключается в том, что он находится внутри контейнера, и после завершения вы можете просто опубликовать контейнер в реестре и извлечь его на узлы Docker в рабочей среде.