Linux环境下Docker容器中SQL Server外部登录预登录响应延迟问题
问题描述
我在Linux环境部署了SQL Server Docker容器,创建命令如下:
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=SA.123456" -u 0:0 -p 1433:1433 --name sql1 --hostname sql1 -d mcr.microsoft.com/mssql/server:2022-latest
容器可正常启动:
docker start sql1
容器内部能正常登录SQL控制台:
docker exec -it sql1 "bash" root@sql1:/# /opt/mssql-tools/bin/sqlcmd -S 127.0.0.1,1433 -U SA Password:
但从Linux宿主机直接使用sqlcmd连接时,出现错误:
/> /opt/mssql-tools/bin/sqlcmd -S 127.0.0.1,1433 -U SA Password:
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login timeout expired.
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : TCP Provider: Timeout error [258].
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Unable to complete login process due to delay in prelogin response.
用telnet可正常建立127.0.0.1:1433的连接(容器停止后连接被拒绝):
/> telnet 127.0.0.1 1433 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'.
确认网络连接正常,但为何会出现预登录响应延迟的错误?
可能的原因及解决方法
1. 宿主机ODBC驱动版本兼容性问题
宿主机安装的ODBC Driver 17可能与容器内SQL Server 2022存在适配问题。可尝试:
- 升级宿主机的ODBC驱动至最新版本
- 切换为ODBC Driver 18版本测试连接
2. Docker端口转发异常
虽然telnet能连通,但Docker的端口转发规则可能在处理SQL Server预登录握手时存在延迟或异常:
- 重启Docker服务重置网络转发:
sudo systemctl restart docker - 检查宿主机iptables规则,确保Docker的端口转发规则未被其他防火墙策略拦截
3. SQL Server预登录配置优化
容器内SQL Server的网络配置可能导致外部连接的预登录握手延迟:
- 进入容器:
docker exec -it sql1 bash - 编辑
/var/opt/mssql/mssql.conf,添加TCP保持连接配置:[network] tcpkeepalive = 1 - 重启容器内SQL Server服务:
/opt/mssql/bin/sqlservr -stop && /opt/mssql/bin/sqlservr -start
4. 宿主机资源不足
若宿主机CPU、内存资源紧张,SQL Server容器无法及时响应预登录请求:
- 用
top或docker stats查看宿主机及容器的资源占用情况 - 增加宿主机资源,或通过
--memory等参数限制容器资源分配,避免资源抢占
5. 调整连接超时参数
尝试延长登录超时时间,或改用localhost作为连接地址测试:
/opt/mssql-tools/bin/sqlcmd -S localhost,1433 -U SA -l 30
其中-l 30表示设置登录超时为30秒
内容的提问来源于stack exchange,提问作者Steffen

