I am trying to set up an Orleans silo inside a Docker container. The client will not be in a container in the beginning.
I am using Docker on Windows in Linux container mode. I am able to have both the client and the silo running and connecting when the client is also in a container.
The silo is configure like this:
var builder = new SiloHostBuilder()
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "DOCKER-SILO";
options.ServiceId = "EZ-DOCKER";
})
.UseAdoNetClustering(options =>
{
options.Invariant = "MySql.Data.MySqlClient";
options.ConnectionString = "server=XXX;user id=orleans;password='XXX';persistsecurityinfo=True;database=orleans;SslMode=None";
})
.Configure<EndpointOptions>(options =>
{
var adressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
options.AdvertisedIPAddress = adressList.First();
options.GatewayPort = 30000);
options.SiloPort = 11111);
})
The client is configured like this:
client = new ClientBuilder()
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "DOCKER-SILO";
options.ServiceId = "EZ-DOCKER";
})
.UseStaticClustering(new IPEndPoint(IPAddress.Parse("192.168.0.13"), 30000))
The silo is run like this:
PS C:\XXX> docker run -p 30000:30000 --expose 11111 --add-host host.docker.internal:192.168.0.13 ezorleanssilolinux
Dockerfile is pretty simple:
FROM mcr.microsoft.com/dotnet/core/runtime:2.1-stretch-slim AS base
WORKDIR /app
FROM base AS final
WORKDIR /app
#COPY --from=publish /app .
COPY ["eZ.Orleans.Silo/publish", "."]
ENTRYPOINT ["dotnet", "eZ.Orleans.Silo.dll"]
When I use 127.0.0.1 as the static gateway ip in the client, it works. When I use any other IP the docker host has, I get the following error in the silo logs:
Gateway received unexpected non-proxied connection from *sgn/01111111-1111-1111-1111-111111111111/11111111 at source address 172.17.0.1:38428
Why am I getting this error when trying on any other address than localhost? netstat -n -a shows me that the silo is listening on 0.0.0.0 on the host.
after a few hours I've managed to make everything works, check out my Silo Code:
return new HostBuilder()
.UseOrleans(builder =>
{
builder
.UseDashboard()
.UseAdoNetClustering(options =>
{
options.Invariant = "System.Data.SqlClient";
options.ConnectionString = _connectionString;
})
.Configure<EndpointOptions>(options =>
{
// Port to use for Silo-to-Silo
options.SiloPort = 11111;
// Port to use for the gateway
options.GatewayPort = 30000;
// IP Address to advertise in the cluster
options.AdvertisedIPAddress = IPAddress.Parse(GetExternalIpAddress());
// The socket used for silo-to-silo will bind to this endpoint
options.GatewayListeningEndpoint = new IPEndPoint(IPAddress.Any, 40000);
// The socket used by the gateway will bind to this endpoint
options.SiloListeningEndpoint = new IPEndPoint(IPAddress.Any, 50000);
})
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "ClusterId-ForSign";
options.ServiceId = "ServiceId-ForSign";
})
.ConfigureApplicationParts(parts =>
{
parts.AddApplicationPart(typeof(UserService).Assembly).WithReferences();
parts.AddApplicationPart(typeof(CompanyService).Assembly).WithReferences();
});
})
.ConfigureServices(services =>
{
services.AddTransient<ICompanyRepository, CompanyRepository>();
services.AddTransient<ICompanyService, CompanyService>();
services.Configure<ConsoleLifetimeOptions>(options =>
{
options.SuppressStatusMessages = true;
});
})
.ConfigureLogging(builder =>
{
builder.AddConsole();
})
.RunConsoleAsync();
}
private static string GetExternalIpAddress() => new WebClient().DownloadString("https://api.ipify.org");