容器化.net core应用程序无法连接到容器化mongo db

Ale*_*der 2 c# mongodb docker .net-core

我正在本地计算机上运行 .net core 应用程序。\n以下是连接到 mongo db 的代码

\n
public BookService(IBookstoreDatabaseSettings settings)\n        {\n            var client = new MongoClient("mongodb://admin:password@localhost:27017");\n            var database = client.GetDatabase("BookstoreDb");\n\n            _books = database.GetCollection<Book>(settings.BooksCollectionName);\n        }\n
Run Code Online (Sandbox Code Playgroud)\n

另外我正在运行以下 docker compose 文件

\n
version: '3'\nservices: \n        mongodb:\n        image: mongo\n        ports:\n            - 27017:27017\n        environment:\n            - MONGO_INITDB_ROOT_USERNAME=admin\n            - MONGO_INITDB_ROOT_PASSWORD=password\n    mongo-express:\n        image: mongo-express\n        ports:\n            - 8081:8081\n        environment:\n            - ME_CONFIG_MONGODB_ADMINUSERNAME=admin\n            - ME_CONFIG_MONGODB_ADMINPASSWORD=password\n            - ME_CONFIG_MONGODB_SERVER=mongodb\n
Run Code Online (Sandbox Code Playgroud)\n

当我使用 dotnet run 运行应用程序,然后请求 http://localhost:5001/api/books 时。一切都工作得很好,API 能够访问 mongo 数据库。

\n

接下来,我使用标准 .net core Docker 文件对我的应用程序进行容器化

\n
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env\nWORKDIR /app\n\n# Copy csproj and restore as distinct layers\nCOPY *.csproj ./\nRUN dotnet restore\n\n# Copy everything else and build\nCOPY . ./\nRUN dotnet publish -c Release -o out\n\n# Build runtime image\nFROM mcr.microsoft.com/dotnet/core/aspnet:3.1\nWORKDIR /app\nCOPY --from=build-env /app/out .\nENTRYPOINT ["dotnet", "BooksApi.dll"]\n
Run Code Online (Sandbox Code Playgroud)\n

接下来我通过运行创建 Docker 映像

\n
docker build -t sample:1.0 .  \n
Run Code Online (Sandbox Code Playgroud)\n

然后我通过添加来扩展 docker-compose

\n
sampleapp:\n        image: sample:1.0\n        ports:\n            - 5001:80\n
Run Code Online (Sandbox Code Playgroud)\n

我正在运行 docker-compose -f .\\mongo.yaml up

\n
docker ps \nCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES\n86ae717ef475        mongo-express       "tini -- /docker-ent\xe2\x80\xa6"   About an hour ago   Up About an hour    0.0.0.0:8081->8081/tcp     sampleapp_mongo-express_1\n3c068306c6e2        mongo               "docker-entrypoint.s\xe2\x80\xa6"   About an hour ago   Up About an hour    0.0.0.0:27017->27017/tcp   sampleapp_mongodb_1\nf275479d2467        sample:1.0          "dotnet BooksApi.dll"    About an hour ago   Up About an hour    0.0.0.0:5001->80/tcp       sampleapp_sampleapp_1\n
Run Code Online (Sandbox Code Playgroud)\n

在浏览器中请求 api http://localhost:5001/api/books\n返回 500

\n

docker 日志 f275479d2467 返回

\n
Hosting environment: Production\nContent root path: /app\nNow listening on: http://[::]:80\nApplication started. Press Ctrl+C to shut down.\nfail: Microsoft.AspNetCore.Server.Kestrel[13]\n      Connection id "0HM3UHJ593UOV", Request id "0HM3UHJ593UOV:00000001": An unhandled exception was thrown by the application.\nSystem.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.\n ---> System.Net.Sockets.SocketException (99): Cannot assign requested address\n   at System.Net.Sockets.Socket.BeginConnectEx(EndPoint remoteEP, Boolean flowContext, AsyncCallback callback, Object state)\n   at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP)\n   at MongoDB.Driver.Core.Connections.TcpStreamFactory.ConnectAsync(Socket socket, EndPoint endPoint, CancellationToken cancellationToken)\n   at MongoDB.Driver.Core.Connections.TcpStreamFactory.CreateStreamAsync(EndPoint endPoint, CancellationToken cancellationToken)\n   at MongoDB.Driver.Core.Connections.BinaryConnection.OpenHelperAsync(CancellationToken cancellationToken)\n   --- End of inner exception stack trace ---\n   at MongoDB.Driver.Core.Connections.BinaryConnection.OpenHelperAsync(CancellationToken cancellationToken)\n   at MongoDB.Driver.Core.Servers.ServerMonitor.HeartbeatAsync(CancellationToken cancellationToken)", LastUpdateTimestamp: "2020-11-01T17:38:08.7321465Z" }] }.\n   at MongoDB.Driver.Core.Clusters.Cluster.ThrowTimeoutException(IServerSelector selector, ClusterDescription description)\n   at MongoDB.Driver.Core.Clusters.Cluster.WaitForDescriptionChangedHelper.HandleCompletedTask(Task completedTask)\n   at MongoDB.Driver.Core.Clusters.Cluster.WaitForDescriptionChanged(IServerSelector selector, ClusterDescription description, Task descriptionChangedTask, TimeSpan timeout, CancellationToken cancellationToken)\n   at MongoDB.Driver.Core.Clusters.Cluster.SelectServer(IServerSelector selector, CancellationToken cancellationToken)\n   at MongoDB.Driver.MongoClient.AreSessionsSupportedAfterServerSelection(CancellationToken cancellationToken)\n   at MongoDB.Driver.MongoClient.AreSessionsSupported(CancellationToken cancellationToken)\n   at MongoDB.Driver.MongoClient.StartImplicitSession(CancellationToken cancellationToken)\n   at MongoDB.Driver.OperationExecutor.StartImplicitSession(CancellationToken cancellationToken)\n   at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)\n   at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)\n   at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)\n   at MongoDB.Driver.IAsyncCursorSourceExtensions.ToList[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)\n   at BooksApi.Services.BookService.Get() in /app/Services/BookService.cs:line 24\n   at lambda_method(Closure , Object , Object[] )\n   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()\n--- End of stack trace from previous location where exception was thrown ---\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()\n--- End of stack trace from previous location where exception was thrown ---\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)\n   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)\n   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)\n
Run Code Online (Sandbox Code Playgroud)\n

mic*_*alk 6

简短回答

将 mongo uri 更改为mongodb://admin:password@mongodb:27017并重建映像。

长答案

当您将应用程序放入 docker 容器中时,localhost不再指您的主机,而是指容器的localhost. 显然你的 mongodb 不是在那里运行,而是在单独的容器中运行。

当您从 docker-compose 运行容器时,它们都连接到由 compose 创建的公共 docker 网络。然后,您撰写的服务名称就是一个 DNS 名称,可以通过该网络解析为容器的 IP。这就是为什么在你的情况下你应该mongodb在连接字符串中使用 mongodb 的主机。您可以在 中阅读更多相关信息docker-compose networking docs

另外如上所述,连接字符串应从环境中获取,而不是硬编码。