Wdrażanie platformy Docker
Napiwek
Nawet jeśli znasz platformę Docker lub Orleans, zaleca się przeczytanie tego artykułu na końcu, aby uniknąć problemów, z którymi mogą wystąpić obejścia.
Ten artykuł i jego przykład są w toku. Wszelkie opinie, żądania ściągnięcia lub sugestie są mile widziane.
Wdrażanie Orleans rozwiązań na platformie Docker
Orleans Wdrażanie na platformie Docker może być trudne, biorąc pod uwagę sposób projektowania orkiestratorów platformy Docker i stosów klastrowania. Najbardziej skomplikowaną rzeczą jest zrozumienie koncepcji overlay Network z modelu sieci Docker Swarm i Kubernetes.
Kontenery platformy Docker i modele sieciowe zostały zaprojektowane do uruchamiania głównie bezstanowych i niezmiennych kontenerów. Dlatego uruchamianie klastra z systemem node.js lub aplikacji Nginx jest dość proste. Jeśli jednak spróbujesz użyć czegoś bardziej skomplikowanego, takiego jak prawdziwa aplikacja klastrowana lub rozproszona (na przykład Orleansoparta na nich), w końcu będziesz mieć problemy z jego skonfigurowaniem. Jest to możliwe, ale nie tak proste, jak aplikacje internetowe.
Klastrowanie platformy Docker składa się z łączenia wielu hostów w celu pracy jako pojedynczej puli zasobów zarządzanych przy użyciu koordynatora kontenerów. Docker Inc. podaj Swarm jako opcję orkiestracji kontenerów, podczas gdy google ma kubernetes (czyli K8s). Istnieją inne orkiestratory, takie jak DC/OS, Mesos, ale w tym dokumencie omówimy Swarm i K8s, ponieważ są one szerzej używane.
Te same interfejsy ziarna i implementacja, które działają w dowolnym miejscu Orleans , są już obsługiwane, będą również działać w kontenerach platformy Docker. Aby można było uruchamiać aplikację w kontenerach platformy Docker, nie trzeba stosować żadnych specjalnych zagadnień.
Omówione tutaj koncepcje Orleans mogą być używane zarówno w wersjach .NET Core, jak i .NET 4.6.1, ale aby zilustrować międzyplatformowy charakter platformy Docker i platformy .NET Core, skupimy się na przykładzie, biorąc pod uwagę, że używasz platformy .NET Core. Szczegółowe informacje dotyczące platformy (Windows/Linux/OSX) można znaleźć w tym artykule.
Wymagania wstępne
W tym artykule założono, że masz zainstalowane następujące wymagania wstępne:
- Docker — Docker4X ma łatwy w użyciu instalator dla głównych obsługiwanych platform. Zawiera on aparat platformy Docker, a także docker Swarm.
- Kubernetes (K8s) — oferta Google dla orkiestracji kontenerów. Zawiera wskazówki dotyczące instalowania narzędzia Minikube (lokalnego wdrożenia K8s) i narzędzia kubectl wraz ze wszystkimi jego zależnościami.
- .NET — międzyplatformowa wersja platformy .NET
- Visual Studio Code (VSCode) — możesz użyć dowolnego środowiska IDE. Program VSCode jest międzyplatformowy, dlatego używamy go do zapewnienia, że działa na wszystkich platformach. Po zainstalowaniu programu VSCode zainstaluj rozszerzenie języka C#.
Ważne
Jeśli nie zamierzasz go używać, nie musisz mieć zainstalowanego rozwiązania Kubernetes. Instalator Platformy Docker4X zawiera już narzędzie Swarm, więc do korzystania z niego nie jest wymagana żadna dodatkowa instalacja.
Uwaga
W systemie Windows instalator platformy Docker włączy funkcję Hyper-V podczas procesu instalacji. Ponieważ ten artykuł i jego przykłady korzystają z platformy .NET Core, używane obrazy kontenerów są oparte na systemie Windows Server NanoServer. Jeśli nie planujesz korzystać z platformy .NET Core i będzie przeznaczony dla platformy .NET 4.6.1 pełnej platformy, używany obraz powinien zawierać system Windows Server Core i wersję 1.4 lub nowszą (która obsługuje tylko pełną strukturę Orleans platformy .NET).
Tworzenie rozwiązania Orleans
Poniższe instrukcje pokazują, jak utworzyć regularne Orleans rozwiązanie przy użyciu nowego dotnet
narzędzia.
Dostosuj polecenia do dowolnego odpowiedniego elementu na platformie. Ponadto struktura katalogów jest tylko sugestią. Dostosuj go do swoich potrzeb.
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
To, co zrobiliśmy do tej pory, to tylko standardowy kod umożliwiający utworzenie struktury rozwiązania i projektów oraz dodanie odwołań między projektami. Nic innego niż zwykły Orleans projekt.
Do czasu pisania tego artykułu 2.0 (która jest jedyną wersją, która obsługuje platformę .NET Core i międzyplatformową) jest w wersji zapoznawczej technologii, Orleans więc jego pakiety NuGet są hostowane w kanale informacyjnym MyGet i nie są publikowane w celu Nuget.org oficjalnego kanału informacyjnego. Aby zainstalować pakiety NuGet w wersji zapoznawczej, użyjemy dotnet
interfejsu wiersza polecenia wymuszające źródło danych i wersję z narzędzia 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, teraz masz wszystkie podstawowe zależności, aby uruchomić prostą Orleans aplikację. Należy pamiętać, że do tej pory nic się nie zmieniło z zwykłej Orleans aplikacji. Teraz dodajmy kod, abyśmy mogli z nim coś zrobić.
Implementowanie Orleans aplikacji
Przy założeniu, że używasz programu VSCode z katalogu rozwiązania, uruchom polecenie code .
. Spowoduje to otwarcie katalogu w programie VSCode i załadowanie rozwiązania.
Jest to właśnie utworzona wcześniej struktura rozwiązania.
Dodaliśmy również pliki Program.cs, OrleansHostWrapper.cs, IGreetingGrain.cs i GreetingGrain.cs odpowiednio do interfejsów i projektów ziarna, a oto kod dla tych plików:
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 (Silos):
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);
}
}
}
}
W tym miejscu nie będziemy szczegółowo mówić o implementacji ziarna, ponieważ wykracza poza zakres tego artykułu. Sprawdź inne dokumenty związane z nim. Te pliki są zasadniczo minimalną Orleans aplikacją i zaczniemy od niej, aby przejść do przodu z resztą tego artykułu.
W tym artykule używamy OrleansAzureUtils
dostawcy członkostwa, ale możesz użyć innych już obsługiwanych przez Orleansprogram .
Plik Dockerfile
Aby utworzyć kontener, platforma Docker używa obrazów. Aby uzyskać więcej informacji na temat tworzenia własnych, możesz zapoznać się z dokumentacją platformy Docker. W tym artykule użyjemy oficjalnych obrazów firmy Microsoft. Na podstawie platform docelowych i programistycznych należy wybrać odpowiedni obraz. W tym artykule używamy microsoft/dotnet:1.1.2-sdk
obrazu opartego na systemie Linux. Można na przykład użyć microsoft/dotnet:1.1.2-sdk-nanoserver
dla systemu Windows. Wybierz ten, który odpowiada Twoim potrzebom.
Uwaga dla użytkowników systemu Windows: Jak wspomniano wcześniej, w wielu platformach używamy platformy .NET Core i Orleans Technical Preview 2.0 w tym artykule. Jeśli chcesz używać platformy Docker w systemie Windows z w pełni wydaną Orleans wersją 1.4 lub nowszą, musisz użyć obrazów opartych na systemie Windows Server Core, ponieważ obrazy oparte na systemie NanoServer i Linux obsługują tylko platformę .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"]
Ten plik Dockerfile zasadniczo pobiera i instaluje debuger VSdbg i uruchamia pusty kontener, zachowując go na zawsze, aby nie trzeba było usuwać/wyłączać podczas debugowania.
Teraz w przypadku środowiska produkcyjnego obraz jest mniejszy, ponieważ zawiera tylko środowisko uruchomieniowe platformy .NET Core, a nie cały zestaw SDK, a plik dockerfile jest nieco prostszy:
Plik Dockerfile:
FROM microsoft/dotnet:1.1.2-runtime
WORKDIR /app
ENTRYPOINT ["dotnet", "OrleansSilo.dll"]
COPY . /app
Plik docker-compose
Plik docker-compose.yml
zasadniczo definiuje (w projekcie) zestaw usług i jego zależności na poziomie usługi. Każda usługa zawiera co najmniej jedno wystąpienie danego kontenera, które jest oparte na obrazach wybranych w pliku Dockerfile. Więcej szczegółów na ten docker-compose
temat można znaleźć w dokumentacji narzędzia docker-compose.
W przypadku wdrożenia typowym przypadkiem Orleans użycia jest posiadanie elementu zawierającego docker-compose.yml
dwie usługi. Jeden dla Orleans silosu, a drugi dla Orleans klienta. Klient będzie mieć zależność od silosu i oznacza to, że zostanie uruchomiony dopiero po uruchomieniu usługi Silo. Innym przypadkiem jest dodanie usługi magazynu/bazy danych/kontenera, na przykład programu SQL Server, który powinien zostać uruchomiony przed klientem i silosem, więc obie usługi powinny mieć na nim zależność.
Uwaga
Przed kontynuowaniem należy pamiętać, że wcięcie ma znaczenie w docker-compose
plikach. Dlatego zwróć uwagę na to, jeśli masz jakiekolwiek problemy.
Poniżej przedstawiono sposób opisywania naszych usług dla tego artykułu:
docker-compose.override.yml (debugowanie):
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 (produkcja):
version: '3.1'
services:
orleans-client:
image: orleans-client
depends_on:
- orleans-silo
orleans-silo:
image: orleans-silo
W środowisku produkcyjnym nie mapujemy katalogu lokalnego ani nie mamy build:
akcji. Przyczyną jest to, że w środowisku produkcyjnym obrazy powinny być kompilowane i wypychane do własnego rejestru platformy Docker.
Ułóż wszystko razem
Teraz mamy wszystkie przenoszone części wymagane do uruchomienia aplikacji Orleans , więc możemy uruchomić nasze Orleans rozwiązanie wewnątrz platformy Docker (Wreszcie!).
Ważne
Następujące polecenia należy wykonać z katalogu rozwiązania.
Najpierw upewnijmy się, że przywracamy wszystkie pakiety NuGet z naszego rozwiązania. Wystarczy to zrobić tylko raz. Należy to zrobić tylko wtedy, gdy zmienisz dowolną zależność pakietu od projektu.
dotnet restore
Teraz skompilujmy nasze rozwiązanie przy użyciu dotnet
interfejsu wiersza polecenia w zwykły sposób i opublikujemy je w katalogu wyjściowym:
dotnet publish -o ./bin/PublishOutput
Napiwek
Używamy publish
tutaj zamiast kompilacji, aby uniknąć problemów z naszymi zestawami ładowanymi dynamicznie w systemie Orleans. Nadal szukamy lepszego rozwiązania.
Po utworzeniu i opublikowaniu aplikacji należy skompilować obrazy dockerfile. Ten krok jest wymagany tylko raz na projekt i powinien być wykonywany ponownie tylko wtedy, gdy zmienisz plik Dockerfile, docker-compose lub z jakiegokolwiek powodu wyczyścisz lokalny rejestr obrazów.
docker-compose build
Wszystkie obrazy używane zarówno w Dockerfile
systemie , jak i docker-compose.yml
są pobierane z rejestru i buforowane na maszynie dewelopera. Obrazy są kompilowane i wszystko jest gotowe do uruchomienia.
Teraz uruchommy go!
# 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
#
Teraz po uruchomieniu elementu docker-compose ps
zobaczysz 2 kontenery uruchomione dla orleansdocker
projektu:
# 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
Uwaga
Jeśli korzystasz z systemu Windows, a kontener używa obrazu systemu Windows jako podstawy, w kolumnie Command (Polecenie) zostanie wyświetlone polecenie względne programu PowerShell do tail
elementu w systemach *NIX, aby kontener zachował ten sam sposób.
Teraz, gdy masz już kontenery, nie musisz go zatrzymywać za każdym razem, gdy chcesz uruchomić aplikację Orleans . Wystarczy zintegrować środowisko IDE w celu debugowania aplikacji wewnątrz kontenera, który został wcześniej zamapowany w pliku docker-compose.yml
.
Skalowanie
Po uruchomieniu projektu redagowania można łatwo skalować aplikację w górę lub w dół przy użyciu docker-compose scale
polecenia :
# 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
Po kilku sekundach zobaczysz usługi skalowane do określonej liczby żądanych wystąpień.
# 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
Ważne
Kolumna Command
na tych przykładach pokazuje tail
polecenie tylko dlatego, że używamy kontenera debugera. Gdybyśmy byli w środowisku produkcyjnym, byłoby to pokazane dotnet OrleansSilo.dll
na przykład.
Docker swarm
Stos klastrowania platformy Docker nosi nazwę Swarm, aby uzyskać więcej informacji, zobacz Docker Swarm.
Aby uruchomić ten artykuł w klastrze, nie masz żadnej dodatkowej Swarm
pracy. Po uruchomieniu docker-compose up -d
w węźle Swarm
będzie on planować kontenery na podstawie skonfigurowanych reguł. To samo dotyczy innych usług opartych na Swarm, takich jak Azure ACS (w trybie Swarm) i AWS ECS Container Service. Wystarczy wdrożyć Swarm
klaster przed wdrożeniem aplikacji dockerizedOrleans .
Uwaga
Jeśli używasz aparatu platformy Docker z trybem Swarm, który ma już obsługę stack
systemu , deploy
i compose
w wersji 3, lepszym podejściem do wdrożenia rozwiązania jest docker stack deploy -c docker-compose.yml <name>
. Pamiętaj tylko, że wymaga pliku redagowania w wersji 3 w celu obsługi aparatu platformy Docker, a większość hostowanych usług, takich jak Azure i AWS, nadal używa wersji 2 i starszych aparatów.
Google Kubernetes (K8s)
Jeśli planujesz hostowanie przy użyciu platformy Kubernetes, dostępny jest dostawca klastrowania utrzymywany przez społeczność pod adresem OrleansContrib\Orleans.Orleans Clustering.Kubernetes. W tym miejscu można znaleźć dokumentację i przykłady dotyczące bezproblemowego hostowania Orleans na platformie Kubernetes przy użyciu dostawcy.
Debugowanie Orleans wewnątrz kontenerów
Teraz, gdy wiesz, jak uruchomić Orleans kontener od podstaw, warto wykorzystać jedną z najważniejszych zasad platformy Docker. Kontenery są niezmienne. Powinny one mieć (prawie) ten sam obraz, zależności i środowisko uruchomieniowe w środowisku deweloperskim, co w środowisku produkcyjnym. Dzięki temu dobre stare stwierdzenie "Działa na mojej maszynie!" nigdy nie dzieje się ponownie. Aby to możliwe, musisz mieć możliwość opracowywania wewnątrz kontenera i zawiera debuger dołączony do aplikacji wewnątrz kontenera.
Istnieje wiele sposobów, aby to osiągnąć przy użyciu wielu narzędzi. Po ocenie kilku, do czasu napisałem ten artykuł, skończyło się na wybraniu jednego, który wygląda bardziej prosty i jest mniej uciążliwy w aplikacji.
Jak wspomniano wcześniej w tym artykule, używamy VSCode
go do tworzenia przykładu, więc oto jak uzyskać debuger dołączony do aplikacji Orleans wewnątrz kontenera.
Najpierw zmień dwa pliki wewnątrz .vscode
katalogu w rozwiązaniu:
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"
}
]
}
Ten plik zasadniczo informuje VSCode
o tym, że za każdym razem, gdy kompilujesz projekt, polecenie zostanie wykonane publish
tak, jak zrobiliśmy to ręcznie wcześniej.
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"
]
}
}
]
}
Teraz możesz po prostu skompilować rozwiązanie ( VSCode
które zostanie opublikowane) i uruchomić zarówno silos, jak i klienta. Spowoduje to wysłanie docker exec
polecenia do uruchomionego docker-compose
wystąpienia usługi/kontenera, aby uruchomić debuger do aplikacji i to jest. Masz debuger dołączony do kontenera i użyj go tak, jakby był to lokalnie uruchomiona Orleans aplikacja. Różnica polega teraz na tym, że znajduje się wewnątrz kontenera, a po zakończeniu możesz po prostu opublikować kontener w rejestrze i ściągnąć go na hostach platformy Docker w środowisku produkcyjnym.