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で確認しました。接続に成功しました!
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:接続を開けませんでした
それらはすべて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コンテナーは同じブリッジネットワークに接続します。
dockerコンテナーのmysqlポートをVMのポートにバインドする必要があります。
これについては、以下のスレッドで詳しく説明しています。
試す価値がある...
Dockerのコンテナーとして実行されているMySQL DBに接続する方法?
@ 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コンテナと通信できます。
結論が間違っている場合は、コメントを歓迎します。
この問題を解決するのに役立つ可能性のある、確認できることがいくつかあります。
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を実行してみます。