2

I'am facing issue with establishing SignalR connection on docker (IIS works well).

Main goal is to run docker compose and send data from nodeRed container to webApp (.net core 3.1 Blazor) and via versa. I made docker network and put there both containers succesfully.

Problem is that my SignalR connections fails with "Connection refused". I see it'll be some banality, but can't find out.

page.razor

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
    .WithUrl("http://AICsystemApp/nodeRedHub") 
    .Build();

    hubConnection.On<string, string>("ReceiveCommand", (user, message) =>
    {
        var encodedMsg = $"{destination}: {message}";
        nodeRedOutput.Add(encodedMsg);
        StateHasChanged();
    });

    await hubConnection.StartAsync();
}

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80       /* tried 8024 */
EXPOSE 443      /* tried 44324 */

FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY ["AICsystemApp/AICsystemApp.csproj", "AICsystemApp/"]
RUN dotnet restore "AICsystemApp/AICsystemApp.csproj"
COPY . .
WORKDIR "/src/AICsystemApp"
RUN dotnet build "AICsystemApp.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "AICsystemApp.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AICsystemApp.dll"]

docker-compose.override.yml

version: '3.4'

services:
 aicsystemapp:
  container_name: AICsystemApp
  environment:
    - ASPNETCORE_ENVIRONMENT=Development
    - ASPNETCORE_URLS=https://+:443;http://+:80
  ports:
    - "8024:80"
    - "44324:443"
  volumes:
    - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
    - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
  networks:
    - my-network
networks:
  my-network:
    external: true

I made SignalR connection with official documentation and just used "http://AICsystemApp/nodeRedHub" instead of "NavigationManager.ToAbsoluteUri("/chathub")" acordingly to this thread : how to run StartAsync connection of signalr blazor client in docker image?

I am confused that docker runs containers in https:// but if I use "https://AICsystemApp/nodeRedHub" I get error: "The remote certificate is invalid according to the validation procedure."
Edit* Find out if I use "https://AICsystemApp:44324/nodeRedHub" I have not errror with https, but same "Connection refused" error. Leads nowhere but interesting.

If you need additional information, I am here ready to respond! :) Thanks in advance.

Also tried ipaddress:port/nodeRedHub, same result.

Ondra Bařina
  • 33
  • 1
  • 6
  • In your yml file port 44324 is pointing to 443 which is ssl so that's why it's working when you put the port in. I also don't see a cert (self-signed or domain) in your yml file. That's probably why you're getting that cert error. You should use a nginx.conf file as a ssl proxy. – GH DevOps Jul 22 '21 at 20:19

2 Answers2

1

I had the same error today and was able to get it working with the following configurations:

  1. you have to use https, with the service name only (https://AICsystemApp/nodeRedHub)
  2. you have to configure kestrel to use the certificates as shown in https://www.yogihosting.com/docker-compose-aspnet-core/

basically generate and mount the trusted dev-cert certificate into the container and use the following additional environment variables:

  - ASPNETCORE_HTTPS_PORT=9000
  - ASPNETCORE_Kestrel__Certificates__Default__Password=<password>
  - ASPNETCORE_Kestrel__Certificates__Default__Path=<mountedpath>/aspnetapp.pfx
  1. since you still have an invalid certificate, you should ignore certificate validation in development. Use only valid certificates in production. SignalR does not use the usual ServicePointManager.ServerCertificateValidationCallback but you have to configure it when building the SignalR connection (which I found here: https://github.com/dotnet/aspnetcore/issues/16919):
Connection = new HubConnectionBuilder()
                .WithUrl("https://host.docker.internal:...",conf =>
{
  if (env.IsDevelopment())
  {
    conf.HttpMessageHandlerFactory = (x) => new HttpClientHandler
    {
      ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
    };
  }
});

I did not test if you could skip step 2, because I needed it anyway. You can try to ignore everything without any certificate, but you will need it in production anyway.

Herm
  • 2,956
  • 19
  • 32
  • Thanks! Took me a while to try it, had other things to do and that had to be side quest. :D BTW -> Step 2 is not necessary! :) – Ondra Bařina Oct 14 '21 at 08:25
  • thank you for the feedback, I will check if I can omit step 2, too, would simplify the solution a lot :) – Herm Oct 15 '21 at 12:18
  • I'm using Docker-Compose. My URL is `https://website/notificationhub` where website is the name of the service that is hosting SignalR and notificationhub is the name of the hub. Adding the HttpClientHandler.DangerousAcceptAnyServerCertificateValidator was necessary. I've had to do this before, but had forgotten about it. It should be in more of the examples. Thanks for the help. – Don Rolling Jul 15 '22 at 21:17
0

I had this problem but to fix it I didn't have to do anything to do with https or certificates. The problem in my case was that that Kestrel was still listening on the default network interface inside the Docker container and I needed to reconfigure it to listen on all interfaces for the connection to work.

So in launchsettings.json I needed to change applicationUrl from "https://localhost:5003;http://localhost:5002" to "https://0.0.0.0:5003;http://0.0.0.0:5002" and then everything worked pefectly.

Neutrino
  • 8,496
  • 4
  • 57
  • 83