Connecting to MongoDB from Docker container running locally

Hi! I’m new to the Dolittle framework. I have an application running in a container on the Dolittle cloud platform and it runs just fine. The problem is that I want to run the application in a container locally, and that causes the application to crash.

I have a MongoDB instance running in a container exposing port 27017.

Here’s my Dockerfile for the application:

I build the image with:
docker build -t image:1 .

And run the container with:
docker run -p 3000:80 image:1

This results in:

---> (Inner Exception #1) System.TimeoutException: 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: Cannot assign requested address [::1]:27017
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
--- 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)" }] }.
   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.WaitForDescriptionChanged(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Clusters.Cluster.SelectServer(IServerSelector selector, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoClient.AreSessionsSupportedAfterServerSelection(CancellationToken cancellationToken)
   at MongoDB.Driver.MongoClient.AreSessionsSupported(CancellationToken cancellationToken)
   at MongoDB.Driver.OperationExecutor.StartImplicitSession(CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
   at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)
   at MongoDB.Driver.IAsyncCursorSourceExtensions.SingleOrDefault[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
   at MongoDB.Driver.IFindFluentExtensions.SingleOrDefault[TDocument,TProjection](IFindFluent`2 find, CancellationToken cancellationToken)
   at Dolittle.Runtime.Events.Processing.MongoDB.EventProcessorOffsetRepository.Get(EventProcessorId eventProcessorId)
   at Dolittle.Runtime.Events.Processing.ScopedEventProcessor.CatchUp()
   at Dolittle.Runtime.Events.Processing.ScopedEventProcessingHub.Register(ScopedEventProcessor processor)
   at Dolittle.Runtime.Events.Processing.BootProcedure.<>c__DisplayClass13_0.<GatherAllEventProcessors>b__2(TenantId t)
   at System.Threading.Tasks.Parallel.<>c__DisplayClass44_0`2.<PartitionerForEachWorker>b__1(IEnumerator& partitionState, Int32 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.Tasks.Parallel.<>c__DisplayClass44_0`2.<PartitionerForEachWorker>b__1(IEnumerator& partitionState, Int32 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
   at System.Threading.Tasks.TaskReplicator.Replica`1.ExecuteAction(Boolean& yieldedBeforeCompletion)
   at System.Threading.Tasks.TaskReplicator.Replica.Execute()<---

---> (Inner Exception #2) System.TimeoutException: 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: Cannot assign requested address [::1]:27017
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
--- 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)" }] }.
   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.WaitForDescriptionChanged(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Clusters.Cluster.SelectServer(IServerSelector selector, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoClient.AreSessionsSupportedAfterServerSelection(CancellationToken cancellationToken)
   at MongoDB.Driver.MongoClient.AreSessionsSupported(CancellationToken cancellationToken)
   at MongoDB.Driver.OperationExecutor.StartImplicitSession(CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
   at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)
   at MongoDB.Driver.IAsyncCursorSourceExtensions.SingleOrDefault[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
   at MongoDB.Driver.IFindFluentExtensions.SingleOrDefault[TDocument,TProjection](IFindFluent`2 find, CancellationToken cancellationToken)
   at Dolittle.Runtime.Events.Processing.MongoDB.EventProcessorOffsetRepository.Get(EventProcessorId eventProcessorId)
   at Dolittle.Runtime.Events.Processing.ScopedEventProcessor.CatchUp()
   at Dolittle.Runtime.Events.Processing.ScopedEventProcessingHub.Register(ScopedEventProcessor processor)
   at Dolittle.Runtime.Events.Processing.BootProcedure.<>c__DisplayClass13_0.<GatherAllEventProcessors>b__2(TenantId t)
   at System.Threading.Tasks.Parallel.<>c__DisplayClass44_0`2.<PartitionerForEachWorker>b__1(IEnumerator& partitionState, Int32 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.Tasks.Parallel.<>c__DisplayClass44_0`2.<PartitionerForEachWorker>b__1(IEnumerator& partitionState, Int32 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
   at System.Threading.Tasks.TaskReplicator.Replica`1.ExecuteAction(Boolean& yieldedBeforeCompletion)
   at System.Threading.Tasks.TaskReplicator.Replica.Execute()<---
<---
<---

I suspect that the problem is that the application in the container can’t connect to the MongoDB instance running on my local machine. What am I doing wrong here?

1 Like

Hi, and welcome to the community!

As far as I understand you are building your application into a docker image and running that image on your local docker host. You are also running a container with MongoDB on that same host. Now you want to connect the two.

This is not really a Dolittle question, more of a Docker/hosting question. The application needs to connect to a database, and if you haven’t changed anything it expects to find that exposed on localhost port 27017. This is controlled in the resources.json -file that you will find in the core\.dolittle -folder.

As long as you’re running your application locally (i.e. directly on your development-machine, not in a docker-container hosted on your development-machine) connecting to a local MongoDB like this is fine. The docker image you’re building does not, however, have a local MongoDB. So you need to set up a network or link between these two running containers and tell your application where to find the MongoDB.

Here’s how to connect two docker-containers.

In your docker-file that you use to build your docker-image you should include a line that overwrites the resources.json -file in the image with one that uses the link you set up (see link above).

For example - if your normal (local-dev) resources.json looks like this

{
    "080844BC-8AE0-44E8-8C1F-F3E75F781A9A": {
        "readModels": {
            "host": "mongodb://localhost:27017",
            "database": "my_project_read_models",
            "useSSL": false
        },
        "eventStore": {
            "host": "mongodb://localhost:27017",
            "database": "my_project_event_store",
            "useSSL": false
        }
    }
}

you could have a local file called docker-resources.json or something like this (this assumes you’ve set up a network in docker where you’ve placed MongoDB on 127.15.0.2)

{
    "080844BC-8AE0-44E8-8C1F-F3E75F781A9A": {
        "readModels": {
            "host": "mongodb://127.15.0.2:27017",
            "database": "my_project_read_models",
            "useSSL": false
        },
        "eventStore": {
            "host": "mongodb://127.15.0.2:27017",
            "database": "my_project_event_store",
            "useSSL": false
        }
    }
}

and then you add a line to your Dockerfile like this to overwrite resources.json in the image.

...
#Build the runtime images
FROM microsoft/dotnet:2.2-sdk-bionic
COPY --from=dotnet-build /Source/core/out /app/core
COPY --from=dotnet-build /Source/bounded-context.json /app/bounded-context.json
COPY --from=node-build /Source/core/wwwroot /app/core/wwwroot

# THIS IS THE NEW LINE
COPY ./path/to/docker-resources.json /app/core/.dolittle/resources.json

ENV ASPNETCORE_ENVIRONMENT production
WORKDIR /app/core
EXPOSE 80
ENTRYPOINT [ "dotnet", "/app/core/core.dll"]

If you host with us we will do this sort of thing automatically to make sure your application is connected to a database with the correct credentials, etc, so don’t worry about overwriting that file in the image.

1 Like