Ошибка аутентификации 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 в контейнере, оставляя его со старыми неправильными значениями.

Другие вопросы по тегам