首先有一些类似的问题,但我已经尝试了我能找到的所有建议,但似乎没有任何效果。如果你能找到我没有提到的,请评论,我会尝试一下。
概要是我正在尝试将 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 错误,但我尝试了解决方法:
TrustServerCertificate=true
- 更改容器上的最小协议:
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="..."