Ошибка аутентификации JDBC от Dockerized SpringBoot к внешнему MariaDB
Я столкнулся с проблемой, связанной с тем, что веб-службе SpringBoot не удалось успешно пройти аутентификацию в голой базе данных MariaDB 10.3.8, когда служба SpringBoot запускается из контейнера Docker. Тот же JAR службы SpringBoot успешно подключается к БД при запуске вне командной строки. Вот подробности:
- сервер Fedora 30 работает на 192.168.99.10
- MariaDB версия 10.3.8 привязана к 0.0.0.0 (не Dockerized)
- MySQL-разъем-5.1.41
- Java OpenJDK 13 работает на Fedora 30
- Docker версия 19.03.0-rc3
- Docker image openjdk:13-alpine
Приложение SpringBoot написано для использования переменных среды для определения местоположения и учетных данных экземпляра базы данных MariaDB.
Класс в сервисе Java, который устанавливает пул JDBC, имеет дополнительное инструментарий для подтверждения того, что значения среды устанавливаются и доступны в момент создания экземпляра пула JDBC:
@Autowired public void setDataSource (DataSource dataSource) { // извлекаем используемые переменные окружения и регистрируем их для отладки String dbhost = System.getenv("DOCKENV_MYSQL_HOST"); String dbport = System.getenv("DOCKENV_MYSQL_PORT"); Строка dbuser = System.getenv("DOCKENV_MYSQL_USERID"); String dbpw = System.getenv("DOCKENV_MYSQL_PASSWORD"); thisLog.info("DOCKENV_MYSQL_HOST=" + dbhost + " DOCKENV_MYSQL_PORT=" + dbport + " DOCKENV_MYSQL_USERID=" + dbuser + " DOCKENV_MYSQL_PASSWORD=" + dbpw); jdbcTemplate = new JdbcTemplate(dataSource); }
Вот что служба SpringBoot записывает в журнал, когда выполняется и вызывается с помощью команды curl на уровне приглашения Linux.
[mdh@fedora1 ~/gitwork/kuberdepends]$ printenv | grep DOCK DOCKENV_MYSQL_PORT = 3306 DOCKENV_MYSQL_PASSWORD = badpassword DOCKENV_MYSQL_HOST = 192.168.99.10 DOCKENV_MYSQL_USERID = dependsapp [mdh@fedora1 ~/gitwork/kuberdepends]$ java -jar target / disabled.jar 1>/dev/null 2>/dev/null& [1] 7814 [mdh@fedora1 ~/gitwork/kuberdepends]$ [mdh@fedora1 ~/gitwork/kuberdepends]$ curl -H "Тип контента: приложение /json" -X GET http://127.0.0.1:8080//depends/api/projects/34 {"project_id":34,"projectstatus_id":0,"clientbusunit_id":2,"clientbusdept_id":2,"factorybusunit_id":11,"factorybusdept_id":23,"имя_проекта":"Объединение портала","shortdescription":"Объединить корпоративные порталы в spectrum.net","longdescription":"Longs desc here","hascapitalspend":"Y","hasexpensespend":"Y","capitalledger":"","anceledger":"","clientpriority":1,"deliverypriority":1,"restricttodept":"N","restricttomembers":"N","createatetime":"2018-05-20 20:51:22.0","updatedatetime":null}[mdh@fedora1 ~/gitwork/kuberdepends]$ [mdh@fedora1 ~/gitwork/kuberdepends]$ [mdh@fedora1 ~/gitwork/kuberdepends]$ [mdh@fedora1 ~/gitwork/kuberdepends]$ cat /logs/springboot/dependsLog.txt | grep зависит app 2019-08-24 13:33:45.077 INFO 7814 --- [main] com.charter.depends.dao.ProjectsDAO: DOCKENV_MYSQL_HOST=192.168.99.10 DOCKENV_MYSQL_PORT=3306 DOCKENV_MYSQL_USERID= зависящий от приложения DOCKENV_MYSQL_PASSWASSWORDW [mdh@fedora1 ~/gitwork/kuberdepends]$
Эта рабочая версия JAR упакована в Docker-контейнер со следующим Dockerfile:
[mdh@fedora1 ~/gitwork/kuberdepends]$ cat Dockerfile.openjdk13alpine # Docker file - использовать в качестве тестового изображения микроразмера с основными командами Linux # 1) использовать альпийское изображение в качестве начального среза # 2) добавить пакеты: iputils, busybox-extras (для telnet), mariadb-client (тестирование доступа MariaDB) # 3) запускает приложение SpringBoot в depen.jar как java -jar /opt/mdhlabs/depends.jar ОТ openjdk:13-альпийский RUN mkdir /opt/mdhlabs COPY ./target/depends.jar /opt/mdhlabs/depends.jar WORKDIR /opt/mdhlabs RUN apk update && apk добавить iputils && apk добавить busybox-extras && apk добавить mariadb-client CMD ["java", "-jar","/opt/mdhlabs/depen.jar"] [mdh@fedora1 ~/gitwork/kuberdepends]$ [mdh@fedora1 ~/gitwork/kuberdepends]$ docker build -t kuberdepends-alp13 -f Dockerfile.openjdk13alpine . (материал опущен здесь для краткости...) Успешно помечены kuberdepends-alp13: последние [mdh@fedora1 ~/gitwork/kuberdepends]$
После остановки этого процесса Springboot и запуска порта версии Docker, отображающего внутренний 8080 на внешний 7777 из основной среды Linux, вот что регистрируется.
[mdh@fedora1 ~/gitwork/kuberdepends]$ docker run --network = host -p 7777: 8080 -d -e DOCKENV_MYSQL_HOST = '192.168.99.10' -e DOCKENV_MYSQL_PORT = '3306' -e DOCKENV_MYSQL_USERID = ' DOCKENV_MYSQL_PASSWORD='badpassword' - имя контейнера kuberdepends kuberdepends-alp13 ВНИМАНИЕ: Опубликованные порты отбрасываются при использовании режима сети хоста. 293d36ed488ca076d050f9579bb54979ff9e469a9d4429ad58204f069dbfd358 [mdh@fedora1 ~/gitwork/kuberdepends]$ [mdh@fedora1 ~/gitwork/kuberdepends]$ curl -H "Тип контента: приложение /json" -X GET http://127.0.0.1:7777//depends/api/projects/34 curl: (7) Не удалось подключиться к порту 127.0.0.1 7777: соединение отклонено [mdh@fedora1 ~/gitwork/kuberdepends]$
Если я получаю доступ к контейнеру Docker, выполняю wget для внутреннего порта прослушивателя 8080 и проверяю файл журнала, сгенерированный службой SpringBoot, вот выходные данные, связанные с попыткой создания экземпляра пула JDBC.
[mdh@fedora1 ~/gitwork/kuberdepends]$ docker exec -it kuberdepends-container sh / opt / mdhlabs # wget --header "Тип контента: application/json" http://127.0.0.1:8080//depends/api/projects/34 Подключение к 127.0.0.1:8080 (127.0.0.1:8080) wget: сервер вернул ошибку: HTTP/1.1 500 /opt/mdhlabs # /opt/mdhlabs # cat /logs/springboot/dependsLog.txt | grep зависит app 2019-08-24 18:52:08.956 ИНФОРМАЦИЯ 1 --- [main] com.charter.depends.dao.ProjectsDAO: DOCKENV_MYSQL_HOST=192.168.99.10 DOCKENV_MYSQL_PORT=3306 DOCKENV_MYSQL_USERID= зависимости app DOCKENV_MYSQL_PASSWORD= java.sql.SQLException: доступ запрещен для пользователя 'depenapp'@'127.0.0.1' (используя пароль: ДА) 2019-08-24 18:56:14.796 ОШИБКА 1 --- [http-nio-8080-exec-1] oaccC [.[.[.[DispatcherServlet]: Servlet.service() для сервлета [dispatcherServlet] в контексте с путь [/ зависит /api] вызвала исключение [Ошибка обработки запроса; вложенное исключение - org.springframework.jdbc.CannotGetJdbcConnectionException: не удалось получить соединение JDBC; Вложенное исключение - java.sql.SQLException: доступ запрещен для пользователя 'depenapp'@'127.0.0.1' (с использованием пароля: ДА)] с основной причиной java.sql.SQLException: доступ запрещен для пользователя 'depenapp'@'127.0.0.1' (используя пароль: ДА) /opt/mdhlabs #
Вот та часть, которая поставила меня в тупик. Это не проблема подключения изнутри контейнера к внешнему хосту, на котором выполняется MariaDB, и это не проблема аутентификации с идентификатором пользователя / паролем зависимость app / badpassword. Если я использую клиент mysql, установленный в контейнере Docker, с учетными данными, к базе данных можно получить доступ.
/ opt / mdhlabs # mysql --user= зависимость app --password=badpassword --host=192.168.99.10 зависит Чтение информации таблицы для заполнения имен таблиц и столбцов Вы можете отключить эту функцию для более быстрого запуска с -A Добро пожаловать на монитор MariaDB. Команды заканчиваются на; или \g. Ваш идентификатор подключения MariaDB 45 Версия сервера: 10.3.8-MariaDB MariaDB Сервер Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab и другие. Напечатайте 'помощь;' или '\h' за помощь. Введите "\c", чтобы очистить текущий оператор ввода. MariaDB [зависит]> выберите project_id, имя проекта из проектов, где project_id=34; +------------+------------------------+ | идентификатор_проекта | имя проекта | +------------+------------------------+ | 34 | Ent Portal Unification | +------------+------------------------+ 1 ряд в наборе (0,000 с) MariaDB [зависит]>
Вот подробности журналов исключений, сгенерированных в Dockerized-версии приложения SpringBoot, когда оно пытается подключиться.
2019-08-24 18: 56: 14.605 ИНФОРМАЦИЯ 1 --- [http-nio-8080-exec-1] ccdepends.services.ProjectController: QUERY action=projectRe 2019-08-24 18:56:14.788 ОШИБКА 1 --- [http-nio-8080-exec-1] oatomcat.jdbc.pool.ConnectionPool: Невозможно создать initi java.sql.SQLException: доступ запрещен для пользователя 'depenapp'@'127.0.0.1' (используя пароль: ДА) в com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964) ~[mysql-connector-java-5.1.41.jar!/:5.1.41] в com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973) ~[mysql-connector-java-5.1.41.jar!/:5.1.41] в com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909) ~[mysql-connector-java-5.1.41.jar!/:5.1.41] в com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:873) ~[mysql-connector-java-5.1.41.jar!/:5.1.41] в com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1710) ~[mysql-connector-java-5.1. at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1226) ~[mysql-connector-java-5.1.41.jar!/:5.1.41] at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2205) ~[mysql-connector-java-5.1.41.jar!/:5.1.41] at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2236) ~[mysql-connector-java-5.1.41.jar!/:5.1 at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2035) ~[mysql-connector-java-5.1.41.jar!/:5.1.41]
Я предполагаю, что внутренняя JVM SpringBoot в контейнере Docker и внутренний двоичный файл клиента mysql в контейнере Docker будут, по-видимому, поступать с одного и того же исходного IP-адреса, когда запрос соединения попадает во внешнюю базу данных MariaDB. Если он работает из клиента mysql внутри контейнера Docker, тот же идентификатор пользователя / пароль должен быть разрешен для подключения при использовании внутри SpringBoot JVM в том же контейнере Docker.
Та же проблема возникает с OpenJDK 12 и openjdk:12-alpine, поэтому я не думаю, что проблема связана с версией в Java. Может ли JAR-файл mysql-connector (версия 5.1.41) иметь проблемы с более новыми версиями Java или с MariaDB 10.3.x?
Любая помощь будет оценена.
1 ответ
Найдена основная причина... Ошибка пилота.
В моем дереве проекта было два отдельных файла application.properties в пути к классам:
$PROJECT/ application.properties
$PROJECT/ SRC / основные / ресурсы / application.properties
Версия в верхней части дерева использовалась для быстрого переопределения некоторых значений для одноразовых тестов, но я забыл скопировать этот файл в образ Docker вместе с
$PROJECT/ цель /depends.jar
Это оставило только внутреннюю версию в src/main/resources/application.properties, которая будет использоваться при выполнении зависящего от объекта jar в контейнере, оставляя его со старыми неправильными значениями.