簡體   English   中英

使用Docker橋接網絡時,無法在集成測試中獲取JDBC連接

[英]Unable to acquire JDBC Connection on integration test when using Docker bridge network

當我在本地運行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測試默認設置。
由於錯誤抱怨數據庫連接,所以我通過Jenkins Audit檢查了數據庫插件。 連接成功!

在此輸入圖像描述

我的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容器名稱。 如果在docker container inspect mysql使用localhost或私有IP更改它,則docker container inspect mysql的錯誤消息是相同的,而Stacktrace在最后兩行有點不同。

對於localhost

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.GenericJDBCException:無法打開連接

無法在spring中打開JPA EntityManager進行事務處理

所有這些都是關於nested exception is javax.persistence.PersistenceException
但是nested exception is org.hibernate.exception.JDBCConnectionException:是我的情況。 閱讀將Java連接到MySQL數據庫
但是因為該插件連接正常,意味着從Jenkins容器到MySQL容器的連接很好。

總結:
1. maven的本地測試通過
2. Jenkins插件連接MySQL成功
3.從Jenkins運行時集成測試失敗
4.本地測試環境是WIN10 64bit; Jenkins在Ubuntu 16.04 64位服務器上的docker容器中運行,MySQL 5.7容器連接到同一個橋接網絡。

您應該將docker container mysql端口綁定到VM中的端口。

這在下面的主題中有很好的解釋。

值得嘗試...
如何連接在docker中作為容器運行的MySQL DB?

感謝@ rohit-thomas 我們將問題縮小到與URL主機相關的問題。
簡單的答案是將spring boot application.properties中的JDBC URL主機更改為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容器可以使用其容器名稱或docker bridge網絡上的私有地址與MySQL容器進行通信。 但是,由於Jenkins構建的應用程序無法做到這一點。 由於MySQL容器端口已綁定到主機,因此應用程序可以通過主機端口與MySQL容器通信。

如果結論錯誤,歡迎提出意見。

您可以檢查的一些內容可能有助於您解決此問題。

  • 在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 run或docker文件中的端口時,您需要映射IP和端口。並在容器中使用相同的docker網絡。

  • 驗證服務器應用程序是否可以訪問您的mysql,反之亦然。 進入docker容器並嘗試ping。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM