从在OpenShift中运行的Python连接到Azure SQL数据库时,驱动程序的SQL_HANDLE_HENV上的SQLAllocHandle失败(0)(SQLDriverConnect)

时间:2019-04-02 12:23:27

标签: python-3.x azure-sql-database pyodbc openshift-3 msodbcsql17

仅当尝试从运行于其中的Python 3.7连接到我的Azure DB时 一个OpenShift容器(FROM rhel7:latest),我看到以下错误:

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

我在MAC,Windows和运行RHEL7基本容器的RHEL7 Virtualbox上的Docker中尝试了完全相同的代码-它始终有效!问题只在于我的容器在OpenShift中运行! 我检查了能否在1433年从Openshift远程登录到我的Azure数据库服务器。

我也启用了ODBC日志,但没有比上述错误更多的信息了。

我还应该检查什么?

这是我在Dockerfile中设置MSODBC驱动程序的方式:

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

这是引发错误的代码:

内部modules.database:

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在Mac或Windows上本地或在RHEL7 VM内为我提供了Docker中有效的容器。 感谢您的浏览!

2 个答案:

答案 0 :(得分:1)

unixODBC试图在当前用户的主目录中找到odbc.ini。它正试图通过looking up the user in /etc/passwd来做到这一点。由于Openshift使用的是/ etc / passwd中不存在的项目特定的UID,因此用户查找将无法进行,并且连接将失败。

要解决此问题,请将以下内容添加到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 :(得分:0)

在Windows上使用django时遇到了相同的问题。 将“ SQL Server 2017客户端”升级到最新客户端后,我的问题解决了。 使用下面的链接下载最新的补丁程序: https://www.microsoft.com/en-us/download/details.aspx?id=56567