Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Sugerencia
Incluso si está familiarizado con Docker o Orleans, se recomienda leer este artículo al final para evitar posibles problemas con soluciones alternativas conocidas.
Este artículo y los ejemplos que contiene son un trabajo en curso. Comentarios, solicitudes de incorporación de cambios o sugerencias son bienvenidos.
Implementación de soluciones de Orleans en Docker
La implementación de Orleans en Docker puede resultar complicada debido al diseño de orquestadores de Docker y conjuntos de clústeres. La parte más complicada es comprender el concepto de red superpuesta desde Docker Swarm y el modelo de red de Kubernetes.
Los contenedores de Docker y los modelos de red se diseñaron principalmente para ejecutar contenedores inmutables e inmutables. La creación de un clúster que ejecuta Node.js o aplicaciones nginx es bastante fácil. Sin embargo, el uso de algo más elaborado, como una aplicación realmente agrupada o distribuida (como una basada en Orleans), podría presentar dificultades de configuración. Es posible, pero no tan sencillo como implementar aplicaciones basadas en web.
La agrupación en clústeres de Docker implica agrupar varios hosts para que funcionen como un único grupo de recursos, administrado mediante un orquestador de contenedores. Docker Inc. proporciona Swarm como opción, mientras que Google ofrece Kubernetes (también conocido como K8s). Existen otros orquestadores como DC/OS y Mesos , pero este documento se centra en Swarm y K8s a medida que se usan más ampliamente.
Las mismas interfaces e implementaciones de grano que se ejecutan en cualquier lugar donde se admite Orleans, también se ejecutan en contenedores de Docker. No se necesitan consideraciones especiales para ejecutar una Orleans aplicación en contenedores de Docker.
Los conceptos que se describen aquí se aplican a las versiones de .NET Core y .NET Framework 4.6.1 de Orleans. Sin embargo, para ilustrar la naturaleza multiplataforma de Docker y .NET Core, los ejemplos se centran en el uso de .NET Core. Es posible que se proporcionen detalles específicos de la plataforma (Windows/Linux/macOS) cuando sea necesario.
Requisitos previos
En este artículo se supone que están instalados los siguientes requisitos necesarios:
- Docker: Docker4X tiene un instalador fácil de usar para las principales plataformas compatibles. Contiene el motor de Docker y Docker Swarm.
- Kubernetes (K8s): oferta de orquestación de contenedores de Google. Incluye instrucciones para instalar Minikube (una implementación de K8s local) y kubectl junto con las dependencias.
- .NET: versión multiplataforma de .NET.
- Visual Studio Code (VSCode): se puede usar cualquier IDE preferido. VSCode se usa aquí porque es multiplataforma, lo que garantiza que los ejemplos funcionen en todas las plataformas. Después de instalar VSCode, instale la extensión de C#.
Importante
La instalación de Kubernetes no es necesaria si no la usa. El instalador de Docker4X ya incluye Swarm, por lo que no se necesita ninguna instalación adicional para Swarm.
Nota
En Windows, el instalador de Docker habilita Hyper-V durante la instalación. Dado que en este artículo y sus ejemplos se usa .NET Core, las imágenes de contenedor usadas se basan en Windows Server NanoServer. Si planea usar .NET Framework 4.6.1 en su lugar, use imágenes basadas en Windows Server Core y Orleans la versión 1.4+ (que solo admite .NET Framework).
Cree una Orleans solución
Las siguientes instrucciones muestran cómo crear una solución estándar Orleans mediante la herramienta dotnet
.
Adapte los comandos según corresponda a la plataforma. La estructura de directorios es simplemente una sugerencia; adaptarlo según sea necesario.
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
Hasta ahora, solo se ha creado código reutilizable para la estructura de soluciones y los proyectos, y se han agregado referencias entre ellos. Esto no es diferente de configurar un proyecto normal Orleans .
En el momento en que se escribió este artículo, Orleans 2.0 (compatible con .NET Core y desarrollo multiplataforma) estaba en Technology Preview. Sus paquetes NuGet se hospedaban en un feed de MyGet, en lugar del feed oficial de NuGet.org. Para instalar los paquetes NuGet en versión preliminar, use la dotnet
CLI, forzando la fuente de origen y la versión desde 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
De acuerdo, todas las dependencias básicas para ejecutar una aplicación sencilla Orleans ahora están en su lugar. Tenga en cuenta que nada ha cambiado de una configuración de aplicación normal Orleans hasta este punto. Ahora, vamos a agregar código para que sea funcional.
Implementación de la Orleans aplicación
Suponiendo que se usa VSCode , ejecute code .
desde el directorio de la solución. Este comando abre el directorio en VSCode y carga la solución.
Esta es la estructura de la solución creada anteriormente.
Program.cs, OrleansHostWrapper.cs, IGreetingGrain.cs y GreetingGrain.cs también se agregaron a los proyectos de interfaces y grains, respectivamente. Este es el código de esos archivos:
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 (cliente):
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);
}
}
}
}
Los detalles de implementación específicos no se tratan aquí, ya que están fuera del ámbito de este artículo. Consulte otros documentos relevantes para obtener más información. Estos archivos representan una aplicación mínima Orleans , que actúa como punto de partida para el resto de este artículo.
En este artículo se usa el OrleansAzureUtils
proveedor de pertenencia, pero se puede usar cualquier otro Orleansproveedor compatible.
El archivo Dockerfile
Docker usa imágenes para crear contenedores. Para más información sobre cómo crear imágenes personalizadas, consulte la documentación de Docker. En este artículo se usan imágenes oficiales de Microsoft. En función de las plataformas de destino y desarrollo, elija la imagen adecuada.
microsoft/dotnet:1.1.2-sdk
, aquí se usa una imagen basada en Linux. Para Windows, microsoft/dotnet:1.1.2-sdk-nanoserver
se podría usar, por ejemplo. Elija el que se adapte a las necesidades.
Nota para los usuarios de Windows: como se mencionó anteriormente, para mantener la compatibilidad multiplataforma, se usan .NET Core y Orleans Technical Preview 2.0 en este artículo. Para usar Docker en Windows con la versión Orleans 1.4+, use imágenes basadas en Windows Server Core, ya que las imágenes basadas en NanoServer y Linux solo admiten .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"]
Este Dockerfile básicamente descarga y instala el depurador VSdbg y inicia un contenedor vacío, mantiene el contenedor activo indefinidamente, por lo que no necesita desmontarse y reiniciarse repetidamente durante la depuración.
Ahora, para producción, la imagen es más pequeña porque solo contiene el entorno de ejecución de .NET Core, no todo el SDK. El Dockerfile también es más sencillo:
Dockerfile:
FROM microsoft/dotnet:1.1.2-runtime
WORKDIR /app
ENTRYPOINT ["dotnet", "OrleansSilo.dll"]
COPY . /app
El archivo docker-compose
El docker-compose.yml
archivo define un conjunto de servicios y sus dependencias dentro de un proyecto en el nivel de servicio. Cada servicio contiene una o varias instancias de un contenedor determinado, en función de las imágenes seleccionadas en el Dockerfile. Obtenga más información sobre docker-compose
en la documentación de docker-compose.
Para una Orleans implementación, un caso de uso común implica un docker-compose.yml
archivo que contiene dos servicios: uno para el Orleans Silo y otro para el Orleans Cliente. El servicio cliente depende del servicio Silo, lo que significa que solo se inicia después de que se ejecute el servicio Silo. Otro escenario podría implicar agregar un almacenamiento o un servicio de base de datos o contenedor (como SQL Server), que debe iniciarse antes del cliente y del silo. En este caso, los servicios de cliente y silo dependen del servicio de base de datos.
Nota
Antes de leer más, tenga en cuenta que la sangríaes relevante en los archivos docker-compose
. Preste atención a él si surgen problemas.
Este es el modo en que se describen los servicios para este artículo:
docker-compose.override.yml (depuración):
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 (producción):
version: '3.1'
services:
orleans-client:
image: orleans-client
depends_on:
- orleans-silo
orleans-silo:
image: orleans-silo
En producción, el directorio local no está asignado ni se incluye la acción build:
. El motivo es que, en un entorno de producción, las imágenes se deben compilar e insertar en un registro privado de Docker.
Todo junto
Ahora que todos los componentes necesarios están listos, vamos a ponerlos juntos para ejecutar la Orleans solución dentro de Docker.
Importante
Se deben ejecutar los comandos siguientes desde el directorio de la solución.
En primer lugar, asegúrese de que se restauran todos los paquetes NuGet de la solución. Normalmente, esto solo necesita hacer una vez, a menos que cambien las dependencias del paquete.
dotnet restore
Ahora, compile la solución con la dotnet
CLI como de costumbre y publíquela en un directorio de salida:
dotnet publish -o ./bin/PublishOutput
Sugerencia
publish
se usa aquí en lugar de build
para evitar problemas con ensamblados cargados dinámicamente en Orleans. Se está buscando una mejor solución.
Con la aplicación compilada y publicada, compile las imágenes de Docker mediante dockerfiles. Este paso normalmente necesita realizar solo una vez por proyecto. Solo debe ser necesario de nuevo si el archivo Dockerfile o docker-compose cambia, o si el registro de imágenes local se limpia por cualquier motivo.
docker-compose build
Todas las imágenes base usadas en Dockerfile
y en docker-compose.yml
se extraen del registro y se almacenan en caché en la máquina de desarrollo. Las imágenes de aplicación se compilan y todo está listo para ejecutarse.
Ahora, vamos a ejecutar la aplicación.
# 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
#
Ahora, ejecutar docker-compose ps
muestra dos contenedores en ejecución para el proyecto 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
Nota
Si en Windows y el contenedor usa una imagen base de Windows, la columna Comando muestra el comando equivalente de PowerShell a tail
en los sistemas *NIX, manteniendo el contenedor en ejecución de forma similar.
Ahora que los contenedores se están ejecutando, no es necesario detenerlos cada vez que la Orleans aplicación necesita iniciarse. Simplemente integre el IDE para depurar la aplicación dentro del contenedor, que se asignó anteriormente en docker-compose.yml
.
Ampliación
Una vez que se ejecute el proyecto de Compose, aumente o reduzca fácilmente la capacidad de la aplicación utilizando el comando 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
Después de unos segundos, los servicios se escalan al número específico de instancias solicitadas.
# 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
Importante
La Command
columna de estos ejemplos muestra el tail
comando debido a que se utiliza el contenedor del depurador. En producción, mostraría dotnet OrleansSilo.dll
, por ejemplo.
Docker Swarm
La pila de agrupación en clústeres de Docker se denomina Swarm. Para más información, consulte Docker Swarm.
Para ejecutar la aplicación descrita en este artículo en un Swarm
clúster, no se necesita ningún trabajo adicional. Ejecutar docker-compose up -d
en un nodo Swarm
asigna contenedores según las reglas configuradas. Lo mismo se aplica a otros servicios basados en Swarm, como Azure Kubernetes Service (AKS) (en modo Swarm) y AWS Elastic Container Service (ECS). Simplemente implemente el Swarm
clúster antes de implementar la aplicación dockerizadaOrleans .
Nota
Si usa un motor de Docker con el modo Swarm que admite stack
, deploy
y compose
v3, un mejor enfoque para implementar la solución es docker stack deploy -c docker-compose.yml <name>
. Tenga en cuenta que requiere un archivo de redacción v3 compatible con el motor de Docker. Muchos servicios hospedados como Azure y AWS siguen usando motores v2 y anteriores.
Google Kubernetes (K8s)
Si planea usar Kubernetes para hospedar Orleans, un proveedor de agrupación en clústeres mantenido por la comunidad está disponible en OrleansContrib\Orleans. Clustering.Kubernetes. Allí, busque documentación y ejemplos sobre el hospedaje Orleans en Kubernetes sin problemas mediante el proveedor.
Depuración de Orleans dentro de contenedores
Ahora que la ejecución Orleans en un contenedor desde cero se entiende, es beneficioso aprovechar uno de los principios más importantes de Docker: inmutabilidad. Los contenedores deben tener (casi) la misma imagen, dependencias y tiempo de ejecución en desarrollo que en producción. Esta práctica ayuda a evitar el problema clásico "Funciona en mi máquina". Para que esto sea posible, se necesita una manera de desarrollar dentro del contenedor, incluida la asociación de un depurador a la aplicación que se ejecuta dentro de él.
Existen varias maneras de lograrlo mediante diversas herramientas. Después de evaluar varias opciones en el momento de escribir, se eligió una que parece más sencilla y menos intrusiva para la aplicación.
Como se mencionó anteriormente, VSCode
se usa para desarrollar el ejemplo. A continuación se muestra cómo adjuntar el depurador a la Orleans aplicación dentro del contenedor:
En primer lugar, modifique dos archivos dentro del .vscode
directorio de la solución:
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"
}
]
}
Este archivo básicamente indica VSCode
que cada vez que el proyecto se compila, ejecuta el publish
comando, similar a cómo se realizó manualmente anteriormente.
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"
]
}
}
]
}
Ahora compile la solución a partir de VSCode
(que también publica) e inicie las configuraciones de Silo y Cliente. VSCode envía un docker exec
comando a la instancia o contenedor del servicio en ejecución docker-compose
para iniciar el depurador asociado a la aplicación. Eso es todo. El depurador está asociado al contenedor y se puede usar de la misma manera que se depura una aplicación Orleans ejecutándose localmente. La diferencia clave es que la aplicación se ejecuta dentro del contenedor. Una vez completado el desarrollo, publique la imagen del contenedor en el registro y descárguela en los hosts de Docker en producción.