ASP.NET Core Web API 服务无法连接到同一网络上的 Docker SQL Server

4
我有一个 ASP.NET Core v3 Web API 服务。它可以正常运行并连接到普通的 Windows 托管的 SQL Server 实例。但是当我尝试将它连接到 Docker Linux 托管的 SQL Server 实例时,它会失败。
以下是一些细节:
- 两个容器都在我的 Windows 10 开发机上运行。 - Web API 服务容器是基于 Linux 的,并且单独使用时运行良好。 - Linux SQL Server 容器单独使用时也可以正常工作。
- 我可以通过 SSMS 连接并运行查询而没有任何问题。
- 两个容器都位于同一个默认的桥接网络中。
- 我运行了 `docker network inspect bridge -f "{{json .Containers }}"` 命令,它列出了两个容器。
这是我的数据库连接字符串:
"Server=localhost;Database=MyDatabase;User Id=MySqlUser;Password=MyPassword"
我还尝试在我的 hosts 文件中添加 localsql 条目设置为 127.0.0.0。 localhost 和 localsql 都可以使用 SSMS 连接到 Docker 数据库而没有问题。
这是实际的错误消息:
"A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 40 - Could not open a connection to SQL Server)"
当我尝试使用 hosts 文件中的 localsql 时,它有一个内部异常,消息为 "Name or service not known"。
2个回答

4
连接字符串指向本地主机。在容器中,本地主机指的是容器本身,因此ASP.NET Core容器会尝试在同一容器上查找SQL Server。
请改用SQL Server容器名称替代本地主机,为了使其生效,您需要创建一个用户定义的网络桥接,将两个容器连接起来:
docker network create sql-server-test

在运行容器时,您需要指定容器连接的网络,例如:

# Please note the --name and --network parameters
docker run -e ACCEPT_EULA=Y -e 'SA_PASSWORD=<PWD>' -d --name sql-server --network sql-server-test mcr.microsoft.com/mssql/server:2019-latest
# Please note the --network parameter
docker run -d -p 8889:80 --name aspnet-core --network sql-server-test aspnet-core

由于两个容器现在已经连接到了同一个网络,您可以在连接字符串中使用 Sql Server 容器的名称(位于相同的 sql-server 中),并使用此连接字符串连接到 Sql Server:

"Data Source=sql-server;Initial Catalog=master;User ID=sa;Password=<PWD>"

关于Docker网络和在容器之间设置通信的其他选项的详细信息,请参见此链接


这似乎会奏效。但我尝试过它,仍然以相同的方式失败了。我还尝试在启动容器时添加“-h”选项,并将值传递到连接字符串中。那也不起作用...如果有任何变化,我会尝试这个想法的几种变体并在此更新。 - Vaccano
使用 Docker 创建的 IP 地址可以让它找到服务器。不过最好使用不那么容易改变的东西。 - Vaccano
@Vaccano 我想我误解了你的问题。现在我假设你没有为容器设置专用网络。我已经更新了答案并提供了必要的步骤。使用这个设置,我能够从一个ASP.NET Core容器访问Sql Server。 - Markus

1

马库斯的回答很好,但我想进一步扩展或使其更全面。基本上它是关于默认桥接和用户定义桥接。 如果使用默认桥接,您也可以通过链接容器来实现此目的。请参阅此文章以获取更多信息。

您还可以使用{{User defined Bridge}}创建用户定义的桥接。

$ docker network create my-net

当您像Markus的示例代码一样创建新容器时,可以在创建命令中指定此桥接器名称。
$ docker create --name my-nginx \
  --network my-net \
  --publish 8080:80 \
  nginx:latest

如果您已经创建了容器,可以使用以下命令将您创建的桥接连接到现有容器。对于SQL服务器和API,请执行此操作(sql1是SQL服务器的名称)。然后您不需要在连接字符串中定义本地主机,因为它们将在同一网络中。
$ docker network connect my-net sql1 

每次停止docker并重新部署(调试)容器时,需要按照以下步骤进行操作,这实际上非常烦人:
  • 首先断开连接:docker network disconnect my-net sql1
  • 删除网络:docker network rm my-net
  • 重新连接:docker network connect my-net sql1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接