Docker 中的 Web api 无法连接到主机上的 SQL Server,并出现登录前握手错误

2024-05-17

首先有一些类似的问题,但我已经尝试了我能找到的所有建议,但似乎没有任何效果。如果你能找到我没有提到的,请评论,我会尝试一下。

概要是我正在尝试将 Docker 容器中的 .NET Core 3.1 Web api 连接到主机上的 SQL Server 2019,但失败并显示System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 0 - Success).

I have:

  • Docker(桌面)版本 20.10.7,使用 WSL2 构建 f0df350
  • SQL Server 开发人员 2019 15.0.2080.9
  • Windows 10 家庭版 21H1

我努力了:

不同的 docker 镜像

根据here https://github.com/dotnet/SqlClient/issues/222人们取得成功mcr.microsoft.com/dotnet/core/aspnet:3.1-bionic代替mcr.microsoft.com/dotnet/core/aspnet:3.1

端口映射

各种形式以docker run, 包括-p 1433:1433, -p 0.0.0.0:1433:1433, -p localhost:1433:1433

连接字符串

我的连接字符串当前是"Server=host.docker.internal;Database=xxx;MultipleActiveResultSets=true;UID=sa;PWD='xxx';Integrated Security=false;TrustServerCertificate=true"

我也尝试过Server=host.docker.internal,1433, Server='tcp:host.docker.internal\\SQLSERVER2019,1433', Server='tcp:host.docker.internal,1433', Server='host.docker.internal,1433'...

SQL 服务器配置

TCP 已启用并侦听所有接口,however我看不到 Docker 桌面配置使用的 192.168.65.0/24 范围内的 IP 地址。

SSMS 在本地工作,如果 Web api 应用程序不在 Docker 容器中,则它会进行连接。

TLS 1.2

一些评论说这是由于较新版本的 SQL Server 出现 TLS 错误,但我尝试了解决方法:

  1. TrustServerCertificate=true
  2. 更改容器上的最小协议:
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

Dockerfile

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-bionic AS base
WORKDIR /app
EXPOSE 80

ENV ASPNETCORE_URLS=http://+:80

FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /
COPY . .
RUN dotnet build my.csproj -c Release -o /app/build

FROM build AS publish
RUN dotnet publish my.csproj -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
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
ENTRYPOINT ["dotnet", "my.dll"]

完整的堆栈跟踪

Microsoft.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 0 - Success)
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at Microsoft.Data.SqlClient.SqlConnection.OpenAsync(CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(DbContext _, Boolean result, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
ClientConnectionId:88dafbd1-163f-486b-a750-ec3dbf5c75ff

Thanks!

[edit]

当我使用 SSMS 连接到本地主机时,我得到一个不同的 SQL Server 实例。所以我尝试使用连接字符串连接到正确的命名实例Server=host.docker.internal\SQLSERVER2019;我收到错误:System.Data.SqlClient.SqlException (0x80131904): 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: 25 - Connection string is not valid)

如果我尝试使用Server=host.docker.internal\\SQLSERVER2019; I get Microsoft.Data.SqlClient.SqlException (0x80131904): 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: 25 - Connection string is not valid)

Note:我将连接字符串设置为环境变量docker run: -e ConnectionStrings__MyConnectionString="..."


我今天遇到了这个问题,我在同一台机器上运行了三个 SQL Server 实例。 2012 年、2014 年和 2016 年。我想连接到 2012 年,因为数据库就在那里。我尝试按照中提到的方式设置端口@thinkOfaNumber 的 https://stackoverflow.com/users/1089267/thinkofanumber回答但这对我不起作用。

有效的方法是在 docker 文件中设置 TLSv1.2;

FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
RUN sed -i 's/TLSv1.2/TLSv1.0/g' /etc/ssl/openssl.cnf
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Docker 中的 Web api 无法连接到主机上的 SQL Server,并出现登录前握手错误 的相关文章

随机推荐