如何解决GitHub Actions中连接Docker SQL Server的登录失败问题
问题现象
- 本地Windows 10环境跑Nuke Build全流程:启动SQL Server Docker容器、执行带EF Core库操作的测试完全正常
- 把相同流程放到GitHub Actions(ubuntu-latest)、Azure DevOps流水线后,Docker镜像能正常拉取、容器能正常启动,但测试代码连接数据库时固定抛出错误:
Microsoft.Data.SqlClient.SqlException : Cannot open database "MyDB" requested by the login. The login failed. Login failed for user 'sa' - 已尝试的排查动作:
- 更换连接串,分别使用localhost宿主机映射端口、
docker inspect获取的容器内网IP作为服务地址 - 参考mssql-docker仓库公开issue里的通用解决方案,没有找到匹配GitHub运行环境的适配方案
- 更换连接串,分别使用localhost宿主机映射端口、
踩中核心坑点说明
这套流程在Windows本地能跑、CI上必挂,本质是三个Windows和Linux Docker环境的行为差异导致的,根本不是配置写错了那么简单:
- 硬编码10秒等待逻辑完全碰运气
本地Docker Desktop上SQL Server 2019启动到可接收登录请求的时间刚好卡在10秒左右,但GitHub Runner的Linux环境受CPU、磁盘IO性能限制,SQL Server完成初始化、开放1433端口的时间经常超过10秒。这时候测试程序发的连接请求根本赶在SQL Server的登录服务就绪之前,自然会报sa登录失败,连后续创建MyDB的步骤都走不到。
- 用容器内网IP连的时候端口写错了
之前试的那个连接串Server=127.17.0.2,1455;...逻辑是错的:1455是宿主机的映射端口,从宿主机访问容器的时候才用这个端口;直接走容器内网IP访问的话,要连容器内部的1433端口,写1455根本连不通。 - Linux版SQL Server的硬性格式要求没对齐
之前设置的SA密码Password_01虽然在Windows版SQL Server上符合复杂度要求,但早期2019版Linux容器镜像有个已知问题:如果密码长度不足16位、初始化环境变量传递时带了不可见字符,会直接导致sa账号密码初始化失败——这时候哪怕容器能正常跑,用你设置的密码永远登不上sa。
可直接修改的调整方案
按下面的点改完,CI环境就能和本地Windows的行为对齐:
- 调整Nuke里的
RunDbContainer目标:- 把SA密码换成满足Linux SQL Server复杂度要求的长密码,比如
Password_01_ForCiTest2024 - 删掉硬写的
Thread.Sleep(10000),换成轮询逻辑:每2秒探测一次SQL Server端口的连通性,最多等60秒,确认能建立连接了再往下走编译、测试的流程
- 把SA密码换成满足Linux SQL Server复杂度要求的长密码,比如
- 统一测试用的连接字符串,不要折腾容器内网IP:
固定用Server=localhost,1455;Database=MyDb;User Id=sa;Password=你设置的长密码;MultipleActiveResultSets=True;TrustServerCertificate=True;这里必须加
TrustServerCertificate=True:Linux环境的.NET SqlClient对TLS证书校验比Windows严格,SQL Server容器默认用自签名证书,不加这个参数的话,连接握手会直接失败,报错信息会伪装成“sa登录失败”,根本找不到根因。 - 不要硬编码容器内网IP,GitHub Runner每次构建的Docker网络段IP是动态分配的,写死的IP下次跑就失效了。
快速定位验证方法
如果改完还报错,先单独跑一步docker logs sql1看容器启动日志:
- 确认有没有打印
SQL Server is now ready for client connections. This is an informational message; no user action is required. - 确认有没有报SA密码复杂度不满足要求的初始化错误
只要日志显示服务完全就绪,再跑测试就不会出现随机的sa登录失败问题。
内容的提问来源于stack exchange,提问作者i-will-lie
相关产品推荐
相关产品推荐

