无法从 Docker 容器连接到外部 SQL Server
Posted
技术标签:
【中文标题】无法从 Docker 容器连接到外部 SQL Server【英文标题】:Can't Connect to External SQL Server From Docker Container 【发布时间】:2020-06-12 20:08:06 【问题描述】:我开发了一个 SpringBoot(Java) 应用程序,该应用程序在端口 1433 上调用外部 SQL Server。SQL Server 实例位于本地(不是本地 SQL Server 实例)。但是,可以使用 IntelliJ 或 SQL 客户端从我的桌面访问它。
我正在使用 Microsoft SQL Server JDBC 连接器与实例进行通信。
如果我从 IntelliJ 运行应用程序一切正常,应用程序可以调用 SQL Server,执行命令并返回结果集。
但是,现在我正在尝试 Dockerize api 应用程序。容器执行通常的 SpringBoot 初始化,但是当它尝试调用 SQL Server 时出现以下错误:
com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host myexternalsqlserver.domain, port 1433 has failed. Error: "myexternalsqlserver.domain. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:234)
at com.microsoft.sqlserver.jdbc.SQLServerException.ConvertConnectExceptionToSQLServerException(SQLServerException.java:285)
at com.microsoft.sqlserver.jdbc.SocketFinder.findSocket(IOBuffer.java:2434)
at com.microsoft.sqlserver.jdbc.TDSChannel.open(IOBuffer.java:659)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:2546)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:2216)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:2067)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:1204)
at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:825)
at java.sql/java.sql.DriverManager.getConnection(Unknown Source)
at java.sql/java.sql.DriverManager.getConnection(Unknown Source)
at com.symetra.SdsApi.SqlConnector.getResultSet(SqlConnector.java:26)
这是我的 Docker 文件
FROM openjdk:11.0.4-jre-slim-buster
VOLUME /tmp
COPY target/myapi-1.0-SNAPSHOT.jar app.jar
EXPOSE 8080
EXPOSE 1433
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -jar /app.jar" ]
这些是我用来构建和运行容器的 Docker 命令:
docker build -t myapi . && docker run -p 8080:8080 -p 1433:1433 --name myapi myapi "java","-jar","myapi-1.0-SNAPSHOT.jar"
我觉得1433端口的映射没必要,只是个实验。我应该能够通过主机上的端口 1433 在容器外部进行通信。主机上的 1433 端口没有被阻止,因为我在容器外运行它没有问题。
最后,这是我正在使用的连接字符串:
//Create Connection Url.
String connectionUrl="jdbc:sqlserver://myexternalsqlserver.domain:1433;database=mydb;user=MyUser;password=MyPassword";
我不确定我在这里做错了什么。我想知道是否需要设置 Docker 网络。
感谢您的帮助!
【问题讨论】:
谁解析了myexternalsqlserver.domain
这个名字?它是 localhost 还是您网络上的其他 ip?另外,你在 linux、mac、windows 上?
【参考方案1】:
它应该可以工作。
NB我假设 myexternalsqlserver.domain
不是您使用的。
测试您的容器的一种方法是在其中插入外壳(或创建一个变体)并尝试解析 SQL Server 的主机名:
docker run --interactive --tty openjdk:11.0.4-jre-slim-buster /bin/bash
# then from within the container's shell
apt update && apt install -y dnsutils
nslookup $SQL_SERVER
如果成功,那就是你的代码。
如果不是,那就是网络。
注意您的容器不需要发布 1443 (--publish=1433:1433
),因为它正在使用该端口(在 SQL Server 上)而不是暴露端口本身。
【讨论】:
我现在在尝试“apt”命令时遇到了这个问题:W:无法获取deb.debian.org/debian/dists/buster/InRelease无法解析“deb.debian.org” 我可以访问那些网址(在浏览器中)。 要清楚......当您尝试运行docker run --interactive --tty openjdk:11.0.4-jre-slim-buster /bin/bash -c "apt update && apt install -y dnsutils && nslookup google.com"
时会发生什么?那应该行得通。如果没有,你有一个不同的问题。
它正在尝试访问 deb.debian.org 并且无法到达那里。因此,它甚至无法安装 dnsutils。我想我可能需要 etc/docker/daemon.json 为我的 dns 网关添加一个 IP 地址。我记得几个月前拉一些 python 的东西时不得不这样做。
@KSS 您可以使用 docker run 命令的 --dns 8.8.8.8
选项添加您的 dns 网关。以上是关于无法从 Docker 容器连接到外部 SQL Server的主要内容,如果未能解决你的问题,请参考以下文章
无法使用桥接网络模式从 docker 容器连接到远程 SQL 服务器