Search code examples
mongodbdockerasp.net-web-apiconnection

Fail to connect to MongoDB from .NET WebAPI using Docker


I have a project using .NET6 web api and MongoDB. Everything works fine running locally. But the connection fails when I dockrized them.

Both containers run correctly. But the request would fail when trying to connect to the DB.

fail: Microsoft.AspNetCore.Server.Kestrel[13]Connection id "0HMM01AL2UEJB", Request id "0HMM01AL2UEJB:00000004": An unhandled exception was thrown by the application.System.TimeoutException: A timeout occurred after 30000ms selecting a server using CompositeServerSelector{ Selectors = MongoDB.Driver.MongoClient+AreSessionsSupportedServerSelector, LatencyLimitingServerSelector{ AllowedLatencyRange = 00:00:00.0150000 }, OperationsCountServerSelector }. Client view of cluster state is { ClusterId : "1", Type : "Unknown", State : "Disconnected", Servers : [{ ServerId: "{ ClusterId : 1, EndPoint : "0.0.0.0:27017" }", EndPoint: "0.0.0.0:27017", ReasonChanged: "Heartbeat", State: "Disconnected", ServerVersion: , TopologyVersion: , Type: "Unknown", HeartbeatException: "MongoDB.Driver.MongoConnectionException: An exception occurred while opening a connection to the server.---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (111): Connection refused 0.0.0.0:27017at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)at MongoDB.Driver.Core.Connections.TcpStreamFactory.Connect(Socket socket, EndPoint endPoint, CancellationToken cancellationToken)at MongoDB.Driver.Core.Connections.TcpStreamFactory.CreateStream(EndPoint endPoint, CancellationToken cancellationToken)at MongoDB.Driver.Core.Connections.BinaryConnection.OpenHelper(CancellationToken cancellationToken)--- End of inner exception stack trace ---at MongoDB.Driver.Core.Connections.BinaryConnection.OpenHelper(CancellationToken cancellationToken)at MongoDB.Driver.Core.Connections.BinaryConnection.Open(CancellationToken cancellationToken)at MongoDB.Driver.Core.Servers.ServerMonitor.InitializeConnection(CancellationToken cancellationToken)at MongoDB.Driver.Core.Servers.ServerMonitor.Heartbeat(CancellationToken cancellationToken)", LastHeartbeatTimestamp: "2022-11-06T15:22:41.8569075Z", LastUpdateTimestamp: "2022-11-06T15:22:41.8569078Z" }] }.at MongoDB.Driver.Core.Clusters.Cluster.ThrowTimeoutException(IServerSelector selector, ClusterDescription description)at MongoDB.Driver.Core.Clusters.Cluster.WaitForDescriptionChangedHelper.HandleCompletedTask(Task completedTask)         at MongoDB.Driver.Core.Clusters.Cluster.WaitForDescriptionChangedAsync(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)at MongoDB.Driver.Core.Clusters.Cluster.SelectServerAsync(IServerSelector selector, CancellationToken cancellationToken)at MongoDB.Driver.MongoClient.AreSessionsSupportedAfterServerSelectionAsync(CancellationToken cancellationToken)at MongoDB.Driver.MongoClient.AreSessionsSupportedAsync(CancellationToken cancellationToken)at MongoDB.Driver.MongoClient.StartImplicitSessionAsync(CancellationToken cancellationToken)at MongoDB.Driver.MongoCollectionImpl1.UsingImplicitSessionAsync[TResult](Func2 funcAsync, CancellationToken cancellationToken)at TodoListWebAPI.Services.DataAccess.GetUser(String username) in /src/TodoListWebAPI/Services/DataAccess.cs:line 33at TodoListWebAPI.Controllers.UserController.LogInOrSignUp(UserModel form) in /src/TodoListWebAPI/Controllers/UserController.cs:line 30at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask1 actionResultValueTask)          at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)          at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)          at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)          at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)          at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)          at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)          at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)          at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)          at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)          at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)          at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)          at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application)

How I ran the containers:
docker run -p 5000:5000 -p 5001:500 1 -e ASPNETCORE_HTTP_PORT=https://+:5001 -e ASPNETCORE_URLS=http://+:5000 --link mongodb:mongodb <my-api-image>

docker run -p 27017:27017 --name mongodb mongo

The connection string in appsettings.json file:

  "MongoDbSettings": {
    "ConnectionString": "mongodb://0.0.0.0:27017",
    ......
  },

I know both containers work when I test them individually. And they are both under the same bridge networks.


Solution

  • Assume

    • WebServer container ip: 172.18.0.2 container_name: AContainer
    • MongoDB container ip: 172.18.0.3 container_name: BContainer

    Then AContainer can communicate with BContainer through BContainer ip 172.18.0.3

    Additionally, if they are both on the non-default network, you can make AContainer communicate with BContainer through BContainer container_name BContainer

    Reference :
    4 Reasons Why Your Docker Containers Can't Talk to Each Other