使用 Docker Compose 的容器化 .net 核心应用程序无法解析 MongoDb 容器名称
Posted
技术标签:
【中文标题】使用 Docker Compose 的容器化 .net 核心应用程序无法解析 MongoDb 容器名称【英文标题】:Containerized .net core application using Docker Compose does not resolve MongoDb container name 【发布时间】:2020-02-01 19:18:35 【问题描述】:我在 Visual Studio 2017(版本 15.9.16)中开发了一个简单的 .Net Core 2.2 单元测试项目,该项目连接到启用容器编排支持的 MongoDb 实例。我的目的是运行一个带有 MongoDb 实例的容器,只要从测试资源管理器窗口启动单元测试,它们就会连接到该容器。我面临的问题是从单元测试代码中我无法连接到MongoDb容器,无法解析docker-compose.yml中定义的服务名称。
这里是 docker-compose.yml 文件的内容:
version: '3.4'
services:
myapp:
image: $DOCKER_REGISTRY-myapp
build:
context: .
dockerfile: myapp/Dockerfile
depends_on:
- mongo
mongo:
image: mongo:latest
应用的Dockerfile内容如下:
FROM microsoft/dotnet:2.2-runtime AS base
WORKDIR /app
FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY myapp/myapp.csproj myapp/
RUN dotnet restore myapp/myapp.csproj
COPY . .
WORKDIR /src/myapp
RUN dotnet build myapp.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish myapp.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "myapp.dll"]
在单元测试代码中,如果我在尝试写入数据库时尝试使用 var client = new MongoClient("mongodb://mongo:27017");
连接到 MongoDb 实例,则会收到以下异常:
在选择服务器 30000 毫秒后发生超时 CompositeServerSelector 选择器 = MongoDB.Driver.MongoClient+AreSessionsSupportedServerSelector, LatencyLimitingServerSelector AllowedLatencyRange = 00:00:00.0150000 。集群状态的客户端视图是 ClusterId : "1", ConnectionMode :“自动”,类型:“未知”,状态:“断开连接”,服务器:[ ServerId: " ClusterId : 1, EndPoint : "Unspecified/mongo:27017" ", 端点:“未指定/mongo:27017”,状态:“断开连接”,类型: “未知”,心跳异常: “MongoDB.Driver.MongoConnectionException:发生异常时 打开与服务器的连接。 ---> System.Net.Sockets.SocketException:未知主机位于 System.Net.Dns.HostResolutionEndHelper(IAsyncResult asyncResult) 在 System.Net.Dns.EndGetHostAddresses(IAsyncResult asyncResult) 在 System.Net.Dns.c.b__25_1(IAsyncResult asyncResult) 在 System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar,Func`2 endFunction,Action`1 endAction,Task`1 承诺,布尔 需要同步) --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 MongoDB.Driver.Core.Connections.TcpStreamFactory.ResolveEndPointsAsync(端点 初始)在 MongoDB.Driver.Core.Connections.TcpStreamFactory.CreateStreamAsync(端点 endPoint,CancellationToken 取消令牌)在 MongoDB.Driver.Core.Connections.BinaryConnection.OpenHelperAsync(CancellationToken cancelToken) --- 内部异常堆栈跟踪结束 --- at MongoDB.Driver.Core.Connections.BinaryConnection.OpenHelperAsync(CancellationToken 取消令牌)在 MongoDB.Driver.Core.Servers.ServerMonitor.HeartbeatAsync(CancellationToken cancelToken)", LastUpdateTimestamp: “2019-10-03T10:00:40.7989018Z”] 。'
如果我尝试使用 System.Net.Dns.GetHostEntry("mongo")
解析 MongoDb 容器服务名称,则会收到此异常:
System.Net.SocketException: '未知主机'
我似乎很清楚,单元测试容器内的 .Net Core 代码无法解析 docker-compose.yml 服务名称。另一方面,如果我在单元测试容器中启动会话,我可以成功执行ping mongo
或telnet mongo 27017
。我还尝试确保 MongoDb 容器已按照 this question 中的建议启动,但没有运气。我的代码或 docker 配置文件中必须缺少某些内容才能启用服务名称解析。任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:您可以为每个服务声明一个网络并关联一个IP地址,然后使用mongo服务的IP地址而不是解析其主机名:
version: '3.4'
services:
myapp:
image: $DOCKER_REGISTRY-myapp
build:
context: .
dockerfile: myapp/Dockerfile
depends_on:
- mongo
networks:
mynetwork:
ipv4_address: 178.25.0.3
mongo:
image: mongo:latest
networks:
mynetwork:
ipv4_address: 178.25.0.2
networks:
mynetwork:
driver: bridge
ipam:
config:
- subnet: 178.25.0.0/24
MongoClient("mongodb://178.25.0.2:27017");
【讨论】:
感谢您的帮助!我是 Docker 的新手,不知道可以为容器设置固定的 IP 地址。但是,正如我在回答中提到的那样,这无法解决我报告的问题,因为原因仅仅是容器没有从测试资源管理器窗口运行。【参考方案2】:在我的单元测试代码中运行System.Net.Dns.GetHostName()
并看到返回的名称是主机名而不是容器名称后,我终于找到了这种行为的原因。我忘了提到我正在从测试资源管理器窗口运行我的单元测试,这样容器支持就被完全忽略了。与我的预期相反,Docker Compose 没有被调用,因此 MongoDb 容器和单元测试项目容器都没有启动,单元测试项目只是在主机内运行。 https://developercommunity.visualstudio.com/idea/554907/allow-running-unit-tests-in-docker.html 已经询问了在 Visual Studio 中启用容器支持时在容器中运行单元测试的功能。请为此功能投票!
【讨论】:
以上是关于使用 Docker Compose 的容器化 .net 核心应用程序无法解析 MongoDb 容器名称的主要内容,如果未能解决你的问题,请参考以下文章
.NET Core容器化之多容器应用部署@Docker-Compose