Ошибка SQLAllocHandle драйвера в SQL_HANDLE_HENV (0) (SQLDriverConnect) при подключении к базе данных SQL Azure из Python, запущенной в OpenShift

#python-3.x #azure-sql-database #pyodbc #openshift-3 #msodbcsql17

#python-3.x #azure-sql-database #pyodbc #openshift-3 #msodbcsql17

Вопрос:

Только при попытке подключиться к моей базе данных Azure из Python 3.7, запущенной в контейнере OpenShift (ИЗ rhel7: последняя версия) Я вижу следующую ошибку:

 sqlalchemy.exc.DBAPIError: (pyodbc.Error) ('IM004', "[IM004][unixODBC][Driver Manager]Driver's SQLAllocHandle on SQL_HANDLE_HENV failed (0) (SQLDriverConnect)
  

Я попробовал точно такой же код в Docker на моем MAC, Windows и RHEL7 Virtualbox, на котором запущен базовый контейнер RHEL7 — он всегда работает! Проблема только в моем контейнере, работающем в OpenShift!
Я проверил, что могу подключиться по telnet к своему серверу Azure DB в 1433 из Openshift.

Я также включил журналы ODBC, но там нет дополнительной информации, кроме указанной выше ошибки.

Что еще я должен проверить?

Вот как я настроил драйвер MSODBC в моем Dockerfile:

 RUN curl https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo amp;amp; 
 yum remove unixODBC-utf16 unixODBC-utf16-devel amp;amp; 
 ACCEPT_EULA=Y yum install -y msodbcsql17 amp;amp; 
 yum install -y unixODBC-devel
  

И вот код, который выдает ошибку:

внутренние модули.база данных:

 pyodbc_connstring_safe = 'DRIVER={{ODBC Driver 17 for SQL Server}};SERVER=' config.settings["DB_HOST"] 
                        ';PORT=1433;DATABASE=' config.settings["DB_NAME"] ';UID=' config.usernames["database"] 
                        ';PWD={};MARS_Connection=Yes'

if config.settings["debug"]:
    print("Using DB connection string: {}".format(pyodbc_connstring_safe.format("SAFE_DB_PASS")))

pyodbc_connstring = pyodbc_connstring_safe.format(config.passwords["database"])

Base = declarative_base()
quoted = urllib.parse.quote_plus(pyodbc_connstring)

def get_engine():
    return create_engine('mssql pyodbc:///?odbc_connect={}'.format(quoted), echo=config.settings["debug"], pool_pre_ping=True)
  

Внутри моего приложения flask (ошибка выдается при вызове ‘has_table’):

 @app.route("/baselinedb", methods=["POST"])
def create_db():
    from modules.database import Base
    engine = database.get_engine()
    if not engine.dialect.has_table(engine, database.get_db_object_name("BaselineDefinition"), schema = 'dbo'):
        Base.metadata.create_all(engine)
    db.session.commit()
    return "OK"
  

Как я упоминал в начале, тот же Dockerfile предоставляет мне рабочий контейнер в Docker либо локально на Mac или Windows, либо внутри виртуальной машины RHEL7.
Спасибо, что посмотрели!

Комментарии:

1. Используете ли вы расширение Flask-SQLAlchemy или расширение Flask-Login для OpenShift? В этом руководстве рассматриваются оба варианта и, возможно, это поможет вам перепроверить конфигурацию в среде OpenShift: blog.openshift.com /…

2. Спасибо @MikeUbezziMSFT, я использую Flask-SQLAlchemy. Я посмотрю на ссылку!

Ответ №1:

unixODBC пытается найти odbc.ini в домашнем каталоге текущего пользователя. Он пытается сделать это, просматривая пользователя в /etc / passwd. Поскольку Openshift использует UID, специфичный для проекта, который не существует в / etc / passwd, пользовательский поиск не будет работать, и соединение не будет выполнено.

Чтобы устранить это, добавьте следующее в файл dockerfile

 ADD entrypoint.sh .
RUN chmod 766 /etc/passwd
..
..
ENTRYPOINT entrypoint.sh
  

И следующее в сценарии точки входа

 export $(id)
echo "default:x:$uid:0:user for openshift:/tmp:/bin/bash" >> /etc/passwd
python3.7 app.py
  

Вышеуказанный файл вставит текущего пользователя в / etc / passwd во время запуска контейнера.

Альтернативным и, вероятно, лучшим подходом может быть использование nss_wrapper:https://cwrap.org/nss_wrapper.html

Комментарии:

1. Очень хороший пример того, как решить эту проблему в вашем образе Docker с помощью nss_wrapper, можно найти здесь: github.com/openshift/jenkins/pull/1024/files

2. @filip-reimer вы знаете, как мы можем сделать это для debian 10? Предоставленное вами решение, похоже, предназначено только для openshift

Ответ №2:

Я столкнулся с той же проблемой при использовании django в Windows. После обновления «клиента SQL Server 2017» до последней версии клиент решает мою проблему. Используйте ссылку ниже для загрузки последнего исправления:https://www.microsoft.com/en-us/download/details.aspx?id=56567