intellij-idea 无法从Docker容器连接到外部SQL Server

z31licg0  于 2022-11-01  发布在  Docker
关注(0)|答案(2)|浏览(154)

我开发了一个SpringBoot(Java)应用程序,它通过端口1433调用外部SQL Server。SQL Server示例位于内部(而不是本地SQL Server示例)。但是,可以使用IntelliJ或SQL客户端从我的桌面访问它。
我正在使用Microsoft SQL Server JDBC连接器与示例进行通信。
如果我从IntelliJ运行应用程序,一切正常,应用程序可以调用SQL Server,执行命令并返回结果集。
然而,现在我尝试对接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"

我不认为Map端口1433是必要的,这只是一个实验。我应该能够通过主机上的端口1433与容器外部通信。端口1433在主机上没有被阻塞,因为我在容器外部运行它没有问题。
最后,这是我正在使用的连接字符串:

//Create Connection Url.
String connectionUrl="jdbc:sqlserver://myexternalsqlserver.domain:1433;database=mydb;user=MyUser;password=MyPassword";

我不知道我在这里做错了什么。我想知道我是否需要设置Docker网络。
谢谢你的帮助!

x6yk4ghg

x6yk4ghg1#

应该可以的。

NB我假设您使用的不是myexternalsqlserver.domain

测试容器的一种方法是将shell装入容器(或创建一个变量),并尝试解析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}

如果成功了,它就是你的代码。
如果不是,那就是网络。

NB您的容器不需要发布1443(--publish=1433:1433),因为它正在使用该端口(在SQL Server上),而不是公开端口本身。

7d7tgy0s

7d7tgy0s2#

同样的问题困扰了我好几天,最后按照下面的步骤解决了它。
在我的例子中,SQL服务器托管在Azure托管示例上,并公开了一个私有端点。但是这个解析的IP被Docker网络/网桥认为是本地运行的应用程序,因为在检查Docker的网桥时(docker network inspect bridge)发现网桥的子网是一个IP地址范围,SQL服务器的解析IP也在该范围内。因此,Docker假定SQL服务器托管在同一本地网络中,而不是在外部(这里是企业网络)。在我的例子中,我正在工作的Windows VM已经在企业的专用网络上。

解决方案:

在docker桌面-〉设置-〉Docker引擎json文件中,添加一个新的键值对"bip": "<local IP address range which is outside of the resolved sql server IP>",重启docker桌面,问题应该得到解决。

相关问题