Windows容器无法连接本地SQL Server,但Linux容器可以
问题现象
连接时抛出错误:
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: 0 - The wait operation timed out.)
- 本地直接运行.NET Core控制台程序,使用以下连接字符串可正常访问:
Server=tcp:(计算机名或localhost),1433;Initial Catalog=(数据库名);Persist Security Info=False;User ID=(用户名);Password=(密码);MultipleActiveResultSets=False;Encrypt=False;TrustServerCertificate=False; - 部署到Linux容器时,使用计算机名或
host.docker.internal可正常连接;但部署到Windows容器时完全失败,Python程序测试结果一致,另一台Windows笔记本也复现该问题。
环境信息
Visual Studio生成的Dockerfile
FROM mcr.microsoft.com/dotnet/runtime:7.0 AS base WORKDIR /app FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build WORKDIR /src COPY ["EmailTestDocker/EmailTestDocker.csproj", "EmailTestDocker/"] RUN dotnet restore "EmailTestDocker/EmailTestDocker.csproj" COPY . . WORKDIR "/src/EmailTestDocker" RUN dotnet build "EmailTestDocker.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "EmailTestDocker.csproj" -c Release -o /app/publish /p:UseAppHost=false FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "EmailTestDocker.dll"]
- 使用Hyper-V,未启用Hyper-V容器
容器内测试结果
- 解析
host.docker.internal失败:Resolve-DnsName host.docker.internal # 报错:host.docker.internal : DNS name does not exist - 解析计算机名返回结果:
Resolve-DnsName (计算机名) # (计算机名).local AAAA 60 Answer fe80::dc77:c5a9:10f9:b3a # (计算机名).local A 60 Answer 172.25.80.1 - 测试1433端口连通性失败:
WARNING: TCP connect to (fe80::dc77:c5a9:10f9:b3a%4 : 1433) failed
WARNING: TCP connect to (172.25.80.1 : 1433) failed
ComputerName : (计算机名)
RemoteAddress : fe80::dc77:c5a9:10f9:b3a%4
RemotePort : 1433
InterfaceAlias : Ethernet
SourceAddress : fe80::a94f:9732:c448:9692%4
PingSucceeded : True
PingReplyDetails (RTT) : 0 ms
TcpTestSucceeded : False nat网络检查结果:[ { "Name": "nat", "Id": "c1eb0498ed676f5b3bebf3a3359cc769599f2395b20ffdf19b73f6bbb55cb8d5", "Created": "2023-08-27T13:58:49.6748484-05:00", "Scope": "local", "Driver": "nat", "EnableIPv6": false, "IPAM": { "Driver": "windows", "Options": null, "Config": [ { "Subnet": "172.25.80.0/20", "Gateway": "172.25.80.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "c0b7c2914187f819659142a2daf3987ec9c1c91abb82e949870d0441ccc77c1f": { "Name": "silly_poincare", "EndpointID": "84651f3c036d038e96047a8836fdf4f486dbec945d0c1ccff2f5cc4aa55edd42", "MacAddress": "00:15:5d:5c:d4:c0", "IPv4Address": "172.25.94.69/16", "IPv6Address": "" } }, "Options": { "com.docker.network.windowsshim.hnsid": "(guid)", "com.docker.network.windowsshim.networkname": "nat" }, "Labels": {} } ]
后续更新(2023年8月29日)
- 局域网内另一台机器使用SSMS连接本地SQL Server,能ping通但无法连接,报错与容器内一致
- SQLCHECK工具关键结果:
- 本地HOSTS文件条目:
192.168.0.129 host.docker.internal 192.168.0.129 gateway.docker.internal 127.0.0.1 kubernetes.docker.internal - 本地关联IP地址:
Address Family Address -------------- ---------------------------- InterNetworkV6 fe80::f5b1:d691:6bd8:2d8a%12 InterNetworkV6 fe80::64c2:f44e:925:574c%57 InterNetworkV6 fe80::ed65:3592:dec4:350b%39 InterNetworkV6 fe80::3bba:af49:b8e:87d7%29 InterNetworkV6 fe80::dc77:c5a9:10f9:b3a%20 InterNetwork 192.168.0.129 InterNetwork 172.8.128.1 InterNetwork 172.25.0.1 InterNetwork 172.24.112.1 InterNetwork 172.25.80.1 - 未发现SQL别名
- 本地HOSTS文件条目:
排查与修复步骤
1. 启用SQL Server TCP/IP协议并配置端口
- 打开SQL Server配置管理器,依次展开
SQL Server网络配置→[你的SQL实例名]的协议 - 右键点击TCP/IP,选择
启用 - 双击TCP/IP,切换到
IP地址标签页:- 滚动到
IPAll段,设置TCP端口为1433 - 确保所有IP地址的
已启用选项设为是(至少保证容器所在的172.25.x.x网段IP启用)
- 滚动到
- 重启SQL Server服务(在
SQL Server服务节点找到对应实例,右键重启)
2. 配置Windows防火墙允许1433端口入站
- 打开Windows Defender防火墙 →
高级设置→入站规则→新建规则 - 选择
端口→ 下一步,指定TCP和特定本地端口为1433 → 下一步 - 选择
允许连接→ 下一步,勾选适用的网络环境(域、专用、公用)→ 下一步 - 命名规则(如“SQL Server 1433端口开放”)并完成
- 额外检查:确保
sqlservr.exe(默认路径C:\Program Files\Microsoft SQL Server\MSSQL[版本号].[实例名]\MSSQL\Binn\sqlservr.exe)被允许通过防火墙
3. 解决容器内host.docker.internal解析问题
- 由于Windows容器无法解析该域名,可直接使用宿主机的物理IP(192.168.0.129)作为连接字符串的服务器地址:
Server=tcp:192.168.0.129,1433;Initial Catalog=(数据库名);... - 或运行容器时挂载本地HOSTS文件,同步解析规则:
docker run -v C:\Windows\System32\drivers\etc\hosts:C:\Windows\System32\drivers\etc\hosts [你的镜像名]
4. 验证SQL Server监听的IP地址
- 执行以下SQL查询,确认SQL Server是否监听非本地IP:
SELECT local_net_address, local_tcp_port FROM sys.dm_exec_connections WHERE session_id = @@SPID; - 如果结果仅显示
127.0.0.1,说明SQL Server仅绑定本地回环地址,需回到配置管理器调整TCP/IP的IP绑定设置
5. 再次验证容器与宿主机的连通性
- 在容器内执行以下命令,测试物理IP的1433端口:
Test-NetConnection -ComputerName 192.168.0.129 -Port 1433 - 若
TcpTestSucceeded返回True,说明连通性正常,此时使用该IP的连接字符串即可成功访问
内容的提问来源于stack exchange,提问作者jdahirkanehl

