使用docker桥网络时,无法在集成测试中获取jdbc连接

kulphzqa  于 2021-06-20  发布在  Mysql
关注(0)|答案(3)|浏览(404)

当我跑的时候 maven test 本地传递。但我在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 test默认设置。
由于错误抱怨数据库连接,所以我检查了由Jenkins审计数据库插件。连接成功!

我的 application.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 或专用ip docker container inspect mysql 错误消息是相同的,而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 test ,如果在ide中再次运行junit测试,则此问题将消失。但这应该与根本原因无关。
搜索错误消息,找到一些类似的问题,但有不同的嵌套异常:
无法为事务打开jpa entitymanager;嵌套的异常是javax.persistence.persistenceexception
spingrest:无法为事务打开jpa entitymanager;嵌套的异常是org.hiberna
无法为事务打开jpa entitymanager;org.hibernate.exception.genericjdbception:无法打开连接
无法为spring中的事务打开jpa entitymanager
所有这些都是关于 nested exception is javax.persistence.PersistenceException 但是 nested exception is org.hibernate.exception.JDBCConnectionException: 这就是我的处境。读取将java连接到mysql数据库
但是,由于该插件连接正常,意味着从jenkins容器到mysql容器的连接正常。
总结:
1maven通过的本地测试
2jenkins插件连接mysql成功
三。当从jenkins运行时,集成测试失败
4本地测试环境为win10 64位;jenkins运行在ubuntu16.04 64位服务器上的docker容器中,mysql 5.7容器连接到同一个网桥网络。

2j4z5cfb

2j4z5cfb1#

感谢@rohit thomas。我们将问题缩小到与url的宿主相关的内容。
简单的答案是在spring引导中更改jdbc url的主机 application.properties 到docker主机ip地址。从 spring.datasource.url=jdbc:mysql://mysql:3306/database?spring.datasource.url=jdbc:mysql://172.17.0.1:3306/database? 如何从docker容器内部连接到机器的本地主机?
这篇文章也有助于最终解决问题。

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
       ...

我的结论是:
从映像构建的jenkins容器能够在dockerbridge网络上用其容器名称或私有地址与mysql容器通信。但是,由于jenkins构建的应用程序无法做到这一点。由于mysql容器端口已绑定到主机,因此应用程序可以通过主机端口与mysql容器通信。
如果结论是错误的,欢迎评论。

u0sqgete

u0sqgete2#

您应该将docker容器mysql端口绑定到vm中的端口。
下面的线程对此进行了很好的解释。
值得一试。。。
如何与docker中作为容器运行的mysql db连接?

x6492ojm

x6492ojm3#

您可以检查一些可能有助于解决此问题的内容。
在application.properties中,尝试使用docker主机ip地址。

spring.datasource.url = jdbc:mysql://mysql:3306/DATABASE_URI_PATH

spring.datasource.url = jdbc:mysql://192.168.99.100:33060/DATABASE_URI_PATH

注意:在docker文件中运行docker或端口时,需要Mapip和端口,并在容器中使用相同的docker网络。
验证您的服务器应用程序是否可以访问mysql,反之亦然。进入docker容器并尝试ping。

相关问题