0

I'm trying to connect to a MongoDB container using a .NET core 3.1 webapi container but every time I build and run the webapi container I get the following exception thrown in one of the services when its attempting to get data using C# MongoDB.Driver from the mongo container:

'A timeout occured after 30000ms selecting a server using CompositeServerSelector{ Selectors = MongoDB.Driver.MongoClient+AreSessionsSupportedServerSelector, LatencyLimitingServerSelector{ AllowedLatencyRange = 00:00:00.0150000 } }. Client view of cluster state is { ClusterId : "1", ConnectionMode : "Automatic", Type : "Unknown", State : "Disconnected", Servers : [{ ServerId: "{ ClusterId : 1, EndPoint : "Unspecified/localhost:27017" }", EndPoint: "Unspecified/localhost:27017", State: "Disconnected", Type: "Unknown", HeartbeatException: "MongoDB.Driver.MongoConnectionException: An exception occurred while opening a connection to the server.
 ---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (10061): No connection could be made because the target machine actively refused it. [::1]:27017
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(Exception source)
   at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
   at System.Net.Sockets.Socket.<>c.<ConnectAsync>b__274_0(IAsyncResult iar)
--- End of stack trace from previous location where exception was thrown ---
   at MongoDB.Driver.Core.Connections.TcpStreamFactory.ConnectAsync(Socket socket, EndPoint endPoint, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Connections.TcpStreamFactory.CreateStreamAsync(EndPoint endPoint, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Connections.BinaryConnection.OpenHelperAsync(CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at MongoDB.Driver.Core.Connections.BinaryConnection.OpenHelperAsync(CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Servers.ServerMonitor.HeartbeatAsync(CancellationToken cancellationToken)", LastUpdateTimestamp: "2020-06-07T05:10:17.3502634Z" }] }.'

I can successfully connect to the MongoDB container using MongoDB compass or even using the same web api IIS express instace, the above exception is only thrown when I try to connect using a docker container. I inspected both containers and confirmed that they are both running on the same network.

Here the Dockerfile for the webapi:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-nanoserver-1903 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

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

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

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

MongoDB container is using the latest official MongoDb image. The docker image is run using the following command :

docker run -d -p 27017-27019:27017-27019 --name mongodb mongo:latest

The webapi appsettings.json looks like this:

{
  "DatabaseSettings": {
    "CollectionName": "collectionName",
    "ConnectionString": "mongodb://host.docker.internal:27017",
    "DatabaseName": "db"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

The .NET core 3.1 webapi was built following Microsofts tutorial

For further information here is what the Startup.cs file looks like:

public void ConfigureServices(IServiceCollection services)
{
    // requires using Microsoft.Extensions.Options
    services.Configure<DatabaseSettings>(
        Configuration.GetSection(nameof(DatabaseSettings)));

    services.AddSingleton<IDatabaseSettings>(sp =>
        sp.GetRequiredService<IOptions<DatabaseSettings>>().Value);

    services.AddSingleton<EarningsService>();

    services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
    {
        builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader();
    }));

    services.AddControllers();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    //app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseCors("CorsPolicy");

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

I've looked at all of the following questions to try and figure out how to connect:

Any help is greatly appreciated. Thank you!

Bridgie
  • 1
  • 3
  • Can you please check whether both of the container are in same docker network? you can inspect docker network ip using docker inspect command. – Taybur Rahman Jun 07 '20 at 06:42
  • https://stackoverflow.com/questions/62229008/how-to-allow-all-hosts-to-a-replica-set-in-mongodb/62233373#62233373 use non-loopback addresses – D. SM Jun 07 '20 at 06:54
  • @TayburRahaman I already state in the question that both containers are on the same docker network. – Bridgie Jun 07 '20 at 16:19
  • @D.SM can you elaborate as to how to use non-loop back ids? I'm not sure what you mean – Bridgie Jun 07 '20 at 16:20
  • The linked answer describes what to do. – D. SM Jun 07 '20 at 16:22
  • The issue was that the I wasn't updating the appsettings.Development.json, it was using localhost instead of docker.host.internal, once I updated that file to match with the appsettings.json file everything worked. Thanks anyway – Bridgie Jun 07 '20 at 17:09

1 Answers1

0

Just for the local development workaround. All the containers has to be on the same network and you need to specify the mongodb container's IP address to the connection string of your web api, something like this

"ConnectionString": "mongodb://:@172.25.0.2:27017/db-name?directConnection=true".

you can get the MongoDB Container's IP address by giving the command

$ docker inspect mongo-container-id

and retrieve the "IPAddress": "172.25.0.2"

Rajkumar Peter
  • 765
  • 7
  • 5