无法从在 Docker (Linux) 中运行的 ASP.NET Core 连接到 SQL Server 命名实例
Posted
技术标签:
【中文标题】无法从在 Docker (Linux) 中运行的 ASP.NET Core 连接到 SQL Server 命名实例【英文标题】:Can't connect to SQL Server named instance from ASP.NET Core running in Docker (Linux) 【发布时间】:2019-10-21 17:47:33 【问题描述】:我有一个应用程序应该使用命名实例连接到在远程服务器上运行的 SQL Server。
使用 IISExpress,我可以连接到 SQL Server,但是从 Docker(Linux 容器)它失败了 - 访问上下文时它只是挂起 - 没有抛出异常或错误消息。例如
var context = serviceScope.ServiceProvider.GetService<AppContext>();
context.Users.ToList();
在调试器中它永远不会到达异常处理程序。
相反,我看到很多这样的输出:
The thread 125 has exited with code 0 (0x0).
The thread 164 has exited with code 0 (0x0).
The thread 0xa4 has exited with code 0 (0x0).
使用 node.js,我甚至可以毫无问题地从 docker 连接到 SQL Server。
当我使用例如[ipaddress or host.docker.internal],1433 - 不幸的是,在远程 SQL Server 上,我无法配置固定端口。
使用 IISExpress 工作(因此在 Windows 上运行) 使用固定端口而不是命名实例连接到在开发计算机上运行的 SQL Server 时有效(但我无法更改我们的生产服务器) 在使用 node.js 时有效!来自 docker 也带有命名实例(两者:带有主机名或 IP 地址 - 所以我可以解析远程名称,防火墙不是问题) 尝试使用 Microsoft 容器作为基础的 ASP.NET Core 2.2 和 3.0preview5,例如FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS 基础连接字符串:
"Data Source=remoteIP\\WEBDB;Initial Catalog=TestDB;User ID=testuser;Password=******;"
还尝试使用“Integrated Security=False;”在连接字符串中
服务器身份验证设置为混合
我可以重现这也是没有实体框架:
var conString = "Data Source=remoteIP\\WEBDB;Initial Catalog=TestDB;Integrated Security=False;User ID=testuser;Password=********";
using (SqlConnection conn = new SqlConnection(conString))
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Users", conn))
conn.Open();
var rows = cmd.ExecuteNonQuery();
Console.WriteLine($"rows: rows");
它会挂在conn.Open();
线上。
知道我能做什么吗?
更新:
输入的连接字符串不正确。 完整示例更新代码编辑
这行得通:
var conString = "Data Source=10.0.75.1,1433;Initial Catalog=TestDB;Integrated Security=False;User ID=testuser;Password=********";
这不起作用:
var conString = "Data Source=10.0.75.1\\Developer;Initial Catalog=TestDB;Integrated Security=False;User ID=testuser;Password=********";
我可以 ping 远程 IP 地址以及远程服务器名称。
不幸的是,由于缺少依赖项,在 ubuntu 映像上安装 mssql-cli 失败。
【问题讨论】:
只使用 一个 反斜杠,如果需要转义则使用两个。 尝试将remoteIP\\WEBDB
改为ServerName\InstanceName
,如果ServerName
解析失败,尝试使用FQDN
。
【参考方案1】:
我知道你解决了这个问题。 我只是为其他人添加更多。 类型
ipconfig
我们可以看到网络的IP
Ethernet adapter vEthernet (DockerNAT):
Connection-specific DNS Suffix . :
IPv4 Address. . . . . . . . . . . : 10.0.75.1
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . :
如果我们在 IIS 上运行应用程序,我们可以使用上述 IP。 但是,如果我们在 docker 上运行,应用程序将无法连接到数据库。
Server=172.17.0.2;Database=VoiconCrochet;User Id=sa;Password=P@ssw0rd123;
【讨论】:
【参考方案2】:Issue #222 in SqlClient repository 解释了问题。
我已经验证这两个选项都适合我:
将基础 Docker 映像文件从 mcr.microsoft.com/dotnet/core/aspnet:3.1.0-buster-slim
更改为 mcr.microsoft.com/dotnet/core/aspnet:3.1.0-bionic
在我的 docker 文件中添加一些步骤:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1.0-buster-slim AS final
RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /usr/lib/ssl/openssl.cnf
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /usr/lib/ssl/openssl.cnf
. . .
【讨论】:
【参考方案3】:尝试将“Connect Timeout=60”添加到您的连接字符串中。
【讨论】:
【参考方案4】:我正在使用 Docker 容器化应用程序。我添加了如下的连接字符串,
services.AddDbContext<OrderContext>(options =>
options.UseSqlServer(Configuration["ConnectionString"]);
);
我的连接字符串如下:
Server=sqlserver ; Database=CustomerDb; User Id=sa;Password=8jkGh47hnDw89Haq8LN2
sqlserver是运行在docker上的sql镜像,
sqlserver:
image: microsoft/mssql-server-linux:latest
container_name: sqlserver
ports:
- "7100"
environment:
- ACCEPT_EULA=Y
- MSSQL_PID=Developer
- SA_PASSWORD=8jkGh47hnDw89Haq8LN2
【讨论】:
你在生产中也使用 sql server 容器吗? 目前尚未投入生产。但我可以在本地 docker 中运行它。【参考方案5】:Data Source
是错误的。命名实例仅使用一个反斜杠。正确的来源是:
remoteIP\WEBDB
反斜杠 needs to be escaped 仅当字符串存储在需要这种转义的介质中时,例如在 C# 字符串或 JSON 字符串中。对于 C#、JSON、javascript 和 C++ 相关语言,转义字符是反斜杠本身,例如:
var connectionString="Data Source=remoteIP\\WEBDB;Initial Catalog=TestDB;User ID=testuser;Password=******;"
或
"ConnectionStrings":
"BloggingDatabase": "Server=(localdb)\\mssqllocaldb;Database=EFGetStarted.ConsoleApp.NewDb;Trusted_Connection=True;"
,
文字 C# 字符串、XML 或 INI 文件不需要转义。以下 C# 行不需要转义。
var connectionString=@"Data Source=remoteIP\WEBDB;Initial Catalog=TestDB;User ID=testuser;Password=******;"
编辑
修复名称只是可能出错的一件事。当 DNS 尝试将无法识别的字符串解析为有效 IP 时,错误的地址很容易将应用程序交给应用程序。
另一个问题是docker容器默认没有网络连接。您必须指定它们可以连接的内容以及内部 IP 和端口如何映射到外部 IP 和端口。
您可以使用 SQL Server CLI 工具 mssql-cli 来测试与服务器的连接,而无需运行您自己的应用程序:
mssql-cli -S InternallyMappedIP\WEBDB -d TestDB -U testuser
【讨论】:
感谢您的快速回复。不幸的是,这不是代码中的问题。我更新了这个例子。正如我所说:如果我在 Windows 上的 IISExpress 中运行它,它会毫无问题地连接,并且不会更改代码 @Norman78 什么也没说。在您配置容器之前,容器没有外部网络连接。 是否您已将容器配置为连接到远程 IP 和端口?使用mssql-cli
从命令行测试连接性,无需每次都启动自己的应用程序
好吧,多做一些实验:我现在使用的不是 buster-slim 图像,而是 3.0.0-preview5-disco,因为它包含更多工具。 ping 服务器工作,如果我使用 10.0.75.1,1433 它工作,如果我使用 10.0.75.1\\Developer 它不以上是关于无法从在 Docker (Linux) 中运行的 ASP.NET Core 连接到 SQL Server 命名实例的主要内容,如果未能解决你的问题,请参考以下文章