我在本地机器上运行.net核心应用程序。以下是连接到mongo db的代码
public BookService(IBookstoreDatabaseSettings settings)
{
var client = new MongoClient("mongodb://admin:password@localhost:27017");
var database = client.GetDatabase("BookstoreDb");
_books = database.GetCollection<Book>(settings.BooksCollectionName);
}此外,我正在运行以下docker组合文件
version: '3'
services:
mongodb:
image: mongo
ports:
- 27017:27017
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=password
mongo-express:
image: mongo-express
ports:
- 8081:8081
environment:
- ME_CONFIG_MONGODB_ADMINUSERNAME=admin
- ME_CONFIG_MONGODB_ADMINPASSWORD=password
- ME_CONFIG_MONGODB_SERVER=mongodb当我使用dotnet运行应用程序时,运行然后请求http://localhost:5001/api/books。一切都运行得很好,api能够连接到mongo数据库。
接下来,我使用标准的.net核心Docker文件来容器化我的应用程序
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "BooksApi.dll"]接下来,我将通过运行以下命令创建Docker镜像
docker build -t sample:1.0 . 然后通过添加以下内容扩展docker-compose
sampleapp:
image: sample:1.0
ports:
- 5001:80我正在运行docker-compose -f .\mongo.yaml up
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
86ae717ef475 mongo-express "tini -- /docker-ent…" About an hour ago Up About an hour 0.0.0.0:8081->8081/tcp sampleapp_mongo-express_1
3c068306c6e2 mongo "docker-entrypoint.s…" About an hour ago Up About an hour 0.0.0.0:27017->27017/tcp sampleapp_mongodb_1
f275479d2467 sample:1.0 "dotnet BooksApi.dll" About an hour ago Up About an hour 0.0.0.0:5001->80/tcp sampleapp_sampleapp_1在浏览器http://localhost:5001/api/books中请求api返回500
docker日志f275479d2467返回
Hosting environment: Production
Content root path: /app
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HM3UHJ593UOV", Request id "0HM3UHJ593UOV:00000001": An unhandled exception was thrown by the application.
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.Sockets.SocketException (99): Cannot assign requested address
at System.Net.Sockets.Socket.BeginConnectEx(EndPoint remoteEP, Boolean flowContext, AsyncCallback callback, Object state)
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP)
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-11-01T17:38:08.7321465Z" }] }.
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.MongoClient.StartImplicitSession(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.ToList[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
at BooksApi.Services.BookService.Get() in /app/Services/BookService.cs:line 24
at lambda_method(Closure , Object , Object[] )
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
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()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)发布于 2020-11-03 18:58:19
简短的回答
将mongo uri更改为mongodb://admin:password@mongodb:27017并重新构建映像。
长长的答案
当您将应用程序放入停靠容器中时,localhost不再指向您的主机,而是指向容器的localhost。显然,mongodb不是在那里运行的,而是在单独的容器中运行的。
当您从docker-compose运行您的容器时,它们都连接到由compose创建的公共docker网络。然后,组合中的服务名称就是DNS名称,可以通过此网络将其解析为容器的IP。这就是为什么在您的例子中应该在连接字符串中使用mongodb作为mongodb的主机。你可以在docker-compose networking docs上阅读更多关于它的内容。
还需要注意的是,连接字符串应该从环境中获取,而不是硬编码。
https://stackoverflow.com/questions/64635716
复制相似问题