Невозможно получить соединение JDBC при тестировании интеграции при использовании сети моста Docker - PullRequest
0 голосов
/ 04 июля 2018

Когда я запускаю 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

При выполнении локального теста все они прошли, используется настройка по умолчанию для теста maven, предоставленная IntelliJ IDEA.
Так как ошибка жалуется на соединение с базой данных, поэтому я проверил Jenkins Audit to Database Plugin. Соединение установлено!

enter image description here

Параметр подключения в моем 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

MySQL в URL - это имя контейнера 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 используется для локального теста. Пока сервер Дженкинса использовал мостовую сеть 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

Когда я запускаю тест JUnit в IntelliJ, он иногда дает сбой в локальной среде. Журнал ошибок выглядит так:

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: это моя ситуация. Читать Подключить Java к базе данных MySQL
однако, поскольку этот плагин подключается нормально, это означает, что подключение из контейнера Jenkins к контейнеру MySQL в порядке.

Обобщить:
1. местный тест с мавеном пройден
2. Подключаем плагин Jenkins к MySQL
3. Интеграционный тест не пройден при запуске из Jenkins
4. локальная среда тестирования - WIN10 64bit; Jenkins работает в док-контейнере на 64-битном сервере Ubuntu 16.04, при этом контейнер MySQL 5.7 подключается к той же мостовой сети.

Ответы [ 3 ]

0 голосов
/ 10 августа 2018

Благодаря @ rohit-thomas . Мы сузим вопрос до того, что связано с хостом URL.
Простой ответ - сменить хост URL JDBC в весенней загрузке application.properties на 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, построенный из образа, может взаимодействовать с контейнером MySQL с его именем контейнера или частным адресом в сети Docker Bridge. Однако, поскольку приложение, созданное Jenkins, не может этого сделать. Поскольку порт контейнера MySQL привязан к хост-машине, приложение может связываться с контейнером MySQL через порт хоста.

Если вывод неправильный, комментарии приветствуются.

0 голосов
/ 12 августа 2018

Некоторые вещи, которые вы можете проверить, могут помочь вам решить эту проблему.

  • В application.properties попробуйте использовать IP-адрес хоста Docker.

    от

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

    до

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

    Примечание: Вам нужно будет сопоставить ваш IP и порт, когда вы запускаете Docker или порты в файле Docker. И использовать ту же сеть Docker среди ваших контейнеров.

  • Проверьте, может ли ваше серверное приложение достичь вашего mysql или наоборот. Зайдите внутрь контейнера докера и попробуйте пинговать.

0 голосов
/ 08 августа 2018

Вы должны привязать порт mysql контейнера Docker к порту в ВМ.

Это хорошо объясняется в следующей ветке.

Стоит попробовать ...
Как подключиться к БД MySQL, работающей в качестве контейнера в Docker?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...