【发布时间】:2020-11-01 18:54:07
【问题描述】:
我正在本地计算机上运行 .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 compose 文件
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 run 运行应用程序,然后请求 http://localhost:5001/api/books。一切正常,api 可以访问 mongo db。
接下来,我将使用标准 .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 logs 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)
【问题讨论】:
-
将 mongo uri 更改为
mongodb://admin:password@mongodb:27017并重建。另请记住,此类信息应通过某些属性或环境变量注入,而不是硬编码。 -
非常感谢,确实解决了这个问题。您能否提供一些上下文,为什么它在容器中运行时需要指向 mongodb。关于您的第二条评论,我完全同意我为自己做的只是 POC,因此一切都是硬编码的。还有一件事,你不想适当地回答这个问题,而不是通过 cmets。
标签: c# mongodb docker .net-core