Java 使用Docker网桥网络时,无法在集成测试中获取JDBC连接
当我在本地运行Java 使用Docker网桥网络时,无法在集成测试中获取JDBC连接,java,mysql,spring,docker,jenkins,Java,Mysql,Spring,Docker,Jenkins,当我在本地运行maven测试时,通过。但在CI服务器上运行时出现此错误 Error Message Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection Stacktrace org.springframework.transaction.Cann
maven测试时,
通过。但在CI服务器上运行时出现此错误
Error Message
Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Stacktrace
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Caused by: java.net.UnknownHostException: mysql
运行本地测试时,它们都通过了,使用IntelliJ IDEA提供的maven测试默认设置。由于错误是关于数据库连接的,所以我检查了Jenkins对数据库插件的审计。连接成功 我的
应用程序.properties
中的连接参数也与此对应
spring.datasource.url=jdbc:mysql://mysql:3306/database?useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.maxActive=5
URL中的MySQL是MySQL docker容器名。如果使用localhost
或docker container inspect mysql
中的私有IP进行更改,则错误消息是相同的,而最后两行的Stacktrace略有不同
对于本地主机
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Caused by: java.net.ConnectException: Connection refused (Connection refused)
对于私有IP
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Caused by: java.net.SocketTimeoutException: connect timed out
我认为不同的是URL中的主机,localhost用于本地测试。
而Jenkins服务器使用Docker桥网络
容器状态为:
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
51ea7c7864a4 mysql:5.7 "docker-entrypoint.s…" 19 hours ago Up 19 hours 0.0.0.0:3306->3306/tcp mysql
de364f7b5eaf maven:3-jdk-8 "/usr/local/bin/mvn-…" 21 hours ago Up 21 hours
optimistic_stallman
a6545591e358 jenkinsci/blueocean "/sbin/tini -- /usr/…" 43 hours ago Up 43 hours 0.0.0.0:50000->50000/tcp, 0.0.0.0:2048->8080/tcp frosty_cray
当我在IntelliJ中运行JUnit测试时,它有时会在本地环境中失败。错误日志如下所示:
Caused by: org.h2.jdbc.JdbcSQLException: Schema "DATABASE" not found; SQL statement:
TRUNCATE TABLE database.data_log
我已经搜索了这个问题,据说h2数据库默认使用大写。
在运行maven测试之后,如果再次在IDE中运行JUnit测试,这个问题将消失。但这与根本原因无关
搜索错误消息,找到一些类似的问题,但有不同的嵌套异常:
所有这些都是关于嵌套异常是javax.persistence.PersistenceException
但是嵌套异常是org.hibernate.exception.JDBCConnectionException:
是我的情况。
阅读
然而,由于插件连接正常,这意味着从Jenkins容器到MySQL容器的连接正常
总结:
1.maven通过的本地测试
2.Jenkins插件连接MySQL成功
3.从Jenkins运行时集成测试失败
4.本地测试环境为WIN10 64位;Jenkins在Ubuntu 16.04 64位服务器上的docker容器中运行,MySQL 5.7容器连接到同一网桥网络。您应该将docker容器MySQL端口绑定到VM中的一个端口
这在下面的线程中得到了很好的解释
值得一试……
多亏了。我们将问题缩小到与URL主机相关的内容。
简单的答案是将spring boot应用程序.properties中JDBC URL的主机更改为docker主机IP地址。从
spring.datasource.url=jdbc:mysql://mysql:3306/database?
到
spring.datasource.url=jdbc:mysql://172.17.0.1:3306/database?
这篇文章也有助于最终解决问题
ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
...
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
...
ip地址显示docker0
4:docker0:mtu 1500 qdisc noqueue state UP组默认值
...
inet 172.17.0.1/16 brd 172.17.255.255范围全局docker0
...
我的结论是:
从映像构建的Jenkins容器能够通过其容器名称或docker bridge网络上的私有地址与MySQL容器通信。然而,由于Jenkins构建的应用程序无法做到这一点。
由于MySQL容器端口已绑定到主机,因此应用程序可以通过主机端口与MySQL容器通信
如果结论是错误的,欢迎评论。您可以检查一些可能有助于解决此问题的内容
- 在application.properties中,尝试使用docker主机IP地址
从
到
注:
在docker运行或docker文件中的端口时,需要映射IP和端口。并在容器之间使用相同的docker网络
- 验证您的服务器应用程序是否可以访问mysql,反之亦然。进入docker容器并尝试ping
如果您正在使用Spring boot并在docker中运行测试数据库,我建议您查看一下,下面是如何以最佳方式使用它的说明:(您可以跳过Spock部分)@MaxFarsikovtestcontainer
看起来很酷,但是,在阅读了他们的文档和示例之后,我没有足够的信心在当前项目中使用它。也许我以后会在某个附带项目上尝试。错误是说,没有发送任何数据包
,这表明您的应用程序和mySQL没有相互通信……您还提到Jenkins和mySQL正在相互通信。。。这很好……但是您确认了mySQL和您的应用程序(部署在远程服务器上的位置)是否正在相互通信吗??更多信息请点击这里@Rohittomas我同意你的观点。问题可能存在于MySQL和应用程序之间。我读过那篇文章,并在我的文章中引用了它。但还是不知道去哪里查。本地测试有时会失败,但在我运行maven测试后会通过,稍后会通过一段时间。。。。该应用程序正在本地运行,运行良好??应用程序托管在另一台服务器上,仅在该服务器上或在本地服务器上失败??最后,它什么时候会失败有时候你调试过那个场景吗??maven测试也将通过-->您是否只为这种情况编写了连接???docker run-d--name mysql-p 3306:3306-e mysql\u ROOT\u PASSWORD=PASSWORD mysql:5.7
已经运行如果是端口问题,插件将无法成功连接。@ShiheZhang我刚刚编辑了我的答案。应来自jdbc:mysql://mysql:3306/DATABASE_URI_PATH 对于jdbc:mysql://192.168.99.100:3306/DATABASE_URI_PATH
spring.datasource.url = jdbc:mysql://mysql:3306/DATABASE_URI_PATH
spring.datasource.url = jdbc:mysql://192.168.99.100:33060/DATABASE_URI_PATH