web-dev-qa-db-ja.com

Dockerブリッジネットワークを使用すると、統合テストでJDBC接続を取得できません

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が提供するMavenテストのデフォルト設定にすべて合格しましたIDEAが使用されます。
エラーがデータベース接続について文句を言うので、Jenkins Audit to Database Pluginで確認しました。接続に成功しました!

enter image description here

My 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またはdocker container inspect mysqlのプライベートIPで変更すると、エラーメッセージは同じですが、スタックトレースは最後の2行で少し異なります。

ローカルホスト用

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を実行した後、JUnitテストをIDE=で再度実行すると、この問題が発生します。ただし、これは根本的な原因とは関係がないはずです。

エラーメッセージを検索し、同様の質問をいくつか見つけますが、ネストされた例外が異なります。

トランザクション用にJPA EntityManagerを開けませんでした;ネストされた例外はjavax.persistence.PersistenceExceptionです

SpingREST:トランザクションのJPA EntityManagerを開けませんでした;ネストされた例外はorg.hibernaです

トランザクションのJPA EntityManagerを開けませんでした; org.hibernate.exception.GenericJDBCException:接続を開けませんでした

春のトランザクションでJPA EntityManagerを開けませんでした

それらはすべてnested exception is javax.persistence.PersistenceExceptionについてです
しかしnested exception is org.hibernate.exception.JDBCConnectionException:は私の状況です。読み取り Connect Java MySQLデータベースへ
ただし、そのプラグインは正常に接続するため、JenkinsコンテナからMySQLコンテナへの接続は問題ありません。

要約:
1。 mavenによるローカルテストに合格
2。 JenkinsプラグインがMySQLに接続し成功
3。 Jenkinsから実行すると統合テストが失敗する
4。ローカルテスト環境はWIN10 64ビットです。 Jenkinsは、Ubuntu 16.04 64ビットサーバー上のdockerコンテナーで実行され、MySQL 5.7コンテナーは同じブリッジネットワークに接続します。

13
Shihe Zhang

dockerコンテナーのmysqlポートをVMのポートにバインドする必要があります。

これについては、以下のスレッドで詳しく説明しています。

試す価値がある...
Dockerのコンテナーとして実行されているMySQL DBに接続する方法?

4

@ rohit-thomas に感謝します。質問をURLのホストに関連するものに絞り込みます。
簡単な答えは、春のブートでJDBC URLのホストを変更することですapplication.propertiesをdocker Host 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ブリッジネットワーク上のコンテナ名またはプライベートアドレスでMySQLコンテナと通信できます。ただし、Jenkinsによって作成されたアプリケーションはそれを実行できません。 MySQLコンテナポートはホストマシンにバインドされているため、アプリケーションはホストポートを介してMySQLコンテナと通信できます。

結論が間違っている場合は、コメントを歓迎します。

2
Shihe Zhang

この問題を解決するのに役立つ可能性のある、確認できることがいくつかあります。

  • Application.propertiesでdocker Host 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 fileで実行する場合は、IPとポートをマッピングする必要があります。コンテナー間で同じdockerネットワークを使用します。

  • サーバーアプリがmysqlに到達できるか、またはその逆かを確認します。 Dockerコンテナーの内部に移動して、pingを実行してみます。

0
Winnnn