Dela via


Docker-distribution

Dricks

Även om du är bekant med Docker eller Orleans, rekommenderar vi att du läser den här artikeln till slutet för att undvika problem som du kan stöta på som har lösningar.

Den här artikeln och dess exempel är ett pågående arbete. Feedback, PR eller förslag är välkomna.

Distribuera Orleans lösningar till Docker

Det Orleans kan vara svårt att distribuera till Docker med tanke på hur Docker-orkestratorer och klustringsstackar har utformats. Det mest komplicerade är att förstå begreppet Overlay Network från Docker Swarm- och Kubernetes-nätverksmodellen.

Docker-containrar och nätverksmodeller har utformats för att köra mestadels tillståndslösa och oföränderliga containrar. Därför är det ganska enkelt att skapa ett kluster som kör node.js- eller Nginx-program. Men om du försöker använda något mer detaljerat, till exempel ett riktigt klustrat eller distribuerat program (t.ex Orleans. -baserade program) får du så småningom problem med att konfigurera det. Det är möjligt, men inte så enkelt som webbaserade program.

Docker-klustring består av att sätta ihop flera värdar för att fungera som en enda resurspool som hanteras med hjälp av en Container Orchestrator. Docker Inc. ge Swarm som alternativ för Container Orchestration medan Google har Kubernetes (även kallat K8s). Det finns andra orchestrators som DC/OS, Mesos, men i det här dokumentet kommer vi att prata om Swarm och K8s eftersom de används mer allmänt.

Samma korniga gränssnitt och implementering som körs var som helst Orleans stöds redan körs även på Docker-containrar. Inga särskilda överväganden krävs för att kunna köra programmet i Docker-containrar.

De begrepp som beskrivs här kan användas på både .NET Core- och .NET 4.6.1-smaker, Orleans men för att illustrera plattformsoberoende egenskaper hos Docker och .NET Core fokuserar vi på exemplet med tanke på att du använder .NET Core. Plattformsspecifik information (Windows/Linux/OSX) kan anges i den här artikeln.

Förutsättningar

Den här artikeln förutsätter att du har följande förutsättningar installerade:

  • Docker – Docker4X har ett lättanvänt installationsprogram för de större plattformar som stöds. Den innehåller Docker-motorn och även Docker Swarm.
  • Kubernetes (K8s) – Googles erbjudande om containerorkestrering. Den innehåller vägledning för att installera Minikube (en lokal distribution av K8s) och kubectl tillsammans med alla dess beroenden.
  • .NET – plattformsoberoende smak av .NET
  • Visual Studio Code (VSCode) – Du kan använda vilken IDE du vill. VSCode är plattformsoberoende så vi använder det för att säkerställa att det fungerar på alla plattformar. När du har installerat VSCode installerar du C#-tillägget.

Viktigt!

Du behöver inte ha Kubernetes installerat om du inte ska använda det. Docker4X-installationsprogrammet innehåller redan Swarm, så ingen extra installation krävs för att använda det.

Kommentar

I Windows aktiverar Docker-installationsprogrammet Hyper-V vid installationsprocessen. Eftersom den här artikeln och dess exempel använder .NET Core baseras de containeravbildningar som används på Windows Server NanoServer. Om du inte planerar att använda .NET Core och kommer att rikta in dig på .NET 4.6.1 fullständigt ramverk, ska avbildningen som används vara Windows Server Core och 1.4+-versionen av Orleans (som endast stöder .NET-fullständigt ramverk).

Skapa Orleans-lösning

Följande instruktioner visar hur du skapar en vanlig Orleans lösning med hjälp av det nya dotnet verktyget.

Anpassa kommandona till vad som är lämpligt på din plattform. Katalogstrukturen är också bara ett förslag. Anpassa den efter dina behov.

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

Det vi har gjort hittills var bara exempelkod för att skapa lösningsstrukturen och projekten och lägga till referenser mellan projekt. Inget annat än ett vanligt Orleans projekt.

När den här artikeln skrevs Orleans är 2.0 (som är den enda versionen som stöder .NET Core och plattformsoberoende) i Technology Preview så att dess NuGet-paket finns i ett MyGet-flöde och publiceras inte till Nuget.org officiella feeden. För att installera förhandsversionen av NuGet-paketen använder dotnet vi CLI som tvingar källflödet och versionen från 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

Ok, nu har du alla grundläggande beroenden för att köra ett enkelt Orleans program. Observera att hittills har inget ändrats från ditt vanliga Orleans program. Nu ska vi lägga till lite kod så att vi kan göra något med den.

Implementera ditt Orleans program

Om du använder VSCode kör du från lösningskatalogen code .. Då öppnas katalogen i VSCode och lösningen läses in.

Det här är lösningsstrukturen som vi skapade tidigare.

Visual Studio Code: Explorer med Program.cs valt.

Vi har också lagt till Program.cs, OrleansHostWrapper.cs, IGreetingGrain.cs och GreetingGrain.cs filer till gränssnitten respektive kornprojekten, och här är koden för dessa filer:

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 (klient):

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);
            }
        }
    }
}

Vi går inte in på detaljer om kornimplementeringen här eftersom den inte omfattas av den här artikeln. Kontrollera andra dokument som är relaterade till det. Dessa filer är i stort sett ett minimalt Orleans program och vi börjar med det för att gå vidare med resten av den här artikeln.

I den här artikeln använder OrleansAzureUtils vi medlemskapsprovider, men du kan använda andra som redan stöds av Orleans.

The Dockerfile

För att skapa containern använder Docker avbildningar. Mer information om hur du skapar din egen finns i Docker-dokumentationen. I den här artikeln ska vi använda officiella Microsoft-avbildningar. Baserat på mål- och utvecklingsplattformarna måste du välja rätt avbildning. I den här artikeln använder microsoft/dotnet:1.1.2-sdk vi en Linux-baserad avbildning. Du kan till exempel använda microsoft/dotnet:1.1.2-sdk-nanoserver för Windows. Välj en som passar dina behov.

Obs! För Windows-användare: Som tidigare nämnts använder vi .NET Core och Orleans Technical Preview 2.0 i den här artikeln för att vara plattformsoberoende. Om du vill använda Docker i Windows med den fullständigt släppta Orleans 1.4+, måste du använda de avbildningar som baseras på Windows Server Core sedan NanoServer och Linux-baserade avbildningar, endast stöd för .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"]

Den här Dockerfile laddar i princip ned och installerar VSdbg-felsökningsprogrammet och startar en tom container, vilket håller den vid liv för alltid så att vi inte behöver riva ned/upp vid felsökning.

För produktion är avbildningen mindre eftersom den bara innehåller .NET Core-körningen och inte hela SDK:t, och dockerfile är lite enklare:

Dockerfile:

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

Docker-compose-filen

Filen docker-compose.yml definierar i princip (inom ett projekt) en uppsättning tjänster och dess beroenden på tjänstnivå. Varje tjänst innehåller en eller flera instanser av en viss container, som baseras på de avbildningar som du har valt i Din Dockerfile. Mer information om finns i docker-compose-dokumentationen.docker-compose

För en Orleans distribution är ett vanligt användningsfall att ha en docker-compose.yml som innehåller två tjänster. En för Orleans Silo och den andra för Orleans Client. Klienten skulle ha ett beroende av Silo och det innebär att den startar först när Silo-tjänsten är igång. Ett annat fall är att lägga till en lagrings-/databastjänst/container, till exempel SQL Server, som bör starta först före klienten och silon, så att båda tjänsterna bör vara beroende av den.

Kommentar

Observera att indrag är viktigt i docker-compose filer innan du läser vidare. Så var uppmärksam på det om du har några problem.

Så här beskriver vi våra tjänster för den här artikeln:

docker-compose.override.yml (Felsökning):

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 (produktion):

version: '3.1'

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

I produktion mappar vi inte den lokala katalogen och vi har inte heller åtgärden build: . Anledningen är att avbildningarna i produktion ska skapas och push-överföras till ditt eget Docker-register.

Sätt ihop allt

Nu har vi alla rörliga delar som krävs för att köra ditt Orleans program, vi kommer att sätta ihop det så att vi kan köra vår Orleans lösning i Docker (äntligen!).

Viktigt!

Följande kommandon bör utföras från lösningskatalogen.

Först ska vi se till att vi återställer alla NuGet-paket från vår lösning. Du behöver bara göra det en gång. Du behöver bara göra det igen om du ändrar ett paketberoende för projektet.

dotnet restore

Nu ska vi skapa vår lösning med dotnet CLI som vanligt och publicera den till en utdatakatalog:

dotnet publish -o ./bin/PublishOutput

Dricks

Vi använder publish här i stället för att skapa för att undvika problem med våra dynamiskt inlästa sammansättningar i Orleans. Vi letar fortfarande efter en bättre lösning för det.

När programmet har skapats och publicerats måste du skapa Dockerfile-avbildningarna. Det här steget krävs bara för att utföras en gång per projekt och bör endast utföras igen om du ändrar Dockerfile, docker-compose eller av någon anledning har rensat ditt lokala avbildningsregister.

docker-compose build

Alla avbildningar som används i båda Dockerfile och docker-compose.yml hämtas från registret och cachelagras på utvecklingsdatorn. Dina avbildningar är byggda och du är redo att köras.

Nu kör vi!

# 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
#

Om du nu kör en docker-compose psvisas två containrar som körs för orleansdocker projektet:

# 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

Kommentar

Om du använder Windows och containern använder en Windows-avbildning som bas visar kolumnen Kommando det relativa PowerShell-kommandot till ett tail på *NIX-system så att containern fortsätter på samma sätt.

Nu när du har dina containrar igång behöver du inte stoppa det varje gång du vill starta programmet Orleans . Allt du behöver är att integrera din IDE för att felsöka programmet i containern som tidigare mappades i .docker-compose.yml

Skalning

När du har kört ditt skrivprojekt kan du enkelt skala upp eller ned ditt program med hjälp av docker-compose scale kommandot:

# 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

Efter några sekunder kommer tjänsterna att skalas till det specifika antalet instanser som du har begärt.

# 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

Viktigt!

Kolumnen Command i dessa exempel visar tail kommandot bara för att vi använder felsökningscontainern. Om vi var i produktion skulle det till exempel visas dotnet OrleansSilo.dll .

Docker swarm

Docker-klustringsstacken heter Swarm. Mer information finns i Docker Swarm.

Om du vill köra den här artikeln i ett Swarm kluster har du inget extra arbete. När du kör docker-compose up -d i en Swarm nod schemalägger den containrar baserat på de konfigurerade reglerna. Detsamma gäller för andra Swarm-baserade tjänster som Azure ACS (i Swarm-läge) och AWS ECS Container Service. Allt du behöver göra är att distribuera klustret Swarm innan du distribuerar ditt dockeriseradeOrleans program.

Kommentar

Om du använder en Docker-motor med Swarm-läget som redan har stöd för stack, deployoch compose v3 är en bättre metod för att distribuera lösningen docker stack deploy -c docker-compose.yml <name>. Tänk bara på att det krävs en v3-skrivfil för att stödja Din Docker-motor, och de flesta värdbaserade tjänster som Azure och AWS använder fortfarande v2 och äldre motorer.

Google Kubernetes (K8s)

Om du planerar att använda Kubernetes som värd Orleansfinns det en community-underhållen klusterprovider tillgänglig i OrleansContrib\Orleans. Clustering.Kubernetes. Där hittar du dokumentation och exempel på hur du kan hantera Orleans i Kubernetes sömlöst med hjälp av providern.

Felsöka Orleans inuti containrar

Nu när du vet hur du kör Orleans i en container från grunden är det bra att använda en av de viktigaste principerna i Docker. Containrar är oföränderliga. Och de bör ha (nästan) samma avbildning, beroenden och körning under utveckling som i produktion. Detta säkerställer den gamla goda instruktionen "Det fungerar på min dator!" händer aldrig igen. För att göra det möjligt måste du ha ett sätt att utveckla inuti containern och det inkluderar att ha ett felsökningsprogram kopplat till ditt program i containern.

Det finns flera sätt att uppnå detta med hjälp av flera verktyg. Efter att ha utvärderat flera, när jag skrev den här artikeln, slutade det med att jag valde en som ser enklare ut och är mindre påträngande i programmet.

Som vi nämnde tidigare i den här artikeln använder VSCode vi för att utveckla exemplet, så här hämtar du felsökningsprogrammet som är kopplat till ditt Orleans program i containern.

Ändra först två filer i katalogen .vscode i din lösning:

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"
        }
    ]
}

Den här filen anger VSCode i princip att när du skapar projektet körs publish kommandot som vi gjorde manuellt tidigare.

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"
                ]
            }
        }
    ]
}

Nu kan du bara skapa lösningen från VSCode (som kommer att publicera) och starta både Silo och klienten. Ett kommando skickas docker exec till den tjänstinstans/container som körs docker-compose för att starta felsökningsprogrammet till programmet och det är allt. Du har det felsökningsprogram som är kopplat till containern och använder det som om det vore ett lokalt program som körs Orleans . Skillnaden nu är att den finns i containern, och när du är klar kan du bara publicera containern i registret och hämta den på dina Docker-värdar i produktion.