使用 pyodbc 将 docker python 连接到 SQL 服务器
Posted
技术标签:
【中文标题】使用 pyodbc 将 docker python 连接到 SQL 服务器【英文标题】:Connect docker python to SQL server with pyodbc 【发布时间】:2018-03-06 10:57:51 【问题描述】:我正在尝试连接在 docker 容器中运行的 pyodbc python 脚本以登录到 MSSQL 数据库我尝试了各种 docker 文件,但无法建立连接(在构建 docker 或 python 时失败尝试连接),有没有人有一个工作 dockerfile,使用 pyodbc:
Dockerfile:
# Use an official Python runtime as a parent image
FROM python:2.7-slim
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
ADD . /app
# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt
# Run app.py when the container launches
CMD ["python", "App.py"]
requirements.TXT
pyodbc
App.Py
import pyodbc
connection = pyodbc.connect('Driver=SQL Server;'
'Server=xxxx;'
'Database=xxx;'
'UID=xxxx;'
'PWD=xxxx')
cursor = connection.cursor()
cursor.execute("SELECT [Id],[Name] FROM [DCMM].[config].[Models]")
for row in cursor.fetchall():
print(row.Name)
connection.close()
构建容器 docker build -t sqltest .
输出:
Sending build context to Docker daemon 4.096kB
Step 1/5 : FROM python:2.7-slim
---> 426d65ab9a72
Step 2/5 : WORKDIR /app
---> Using cache
---> 725f35122880
Step 3/5 : ADD . /app
---> 3feb8b7744f7
Removing intermediate container 4214091a111a
Step 4/5 : RUN pip install -r requirements.txt
---> Running in 27aa4dcfe738
Collecting pyodbc (from -r requirements.txt (line 1))
Downloading pyodbc-4.0.17.tar.gz (196kB)
Building wheels for collected packages: pyodbc
Running setup.py bdist_wheel for pyodbc: started
Running setup.py bdist_wheel for pyodbc: finished with status 'error'
Failed building wheel for pyodbc
Complete output from command /usr/local/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-EfWsmy/pyodbc/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" bdist_wheel -d /tmp/tmpa3S13tpip-wheel- --python-tag cp27:
running bdist_wheel
running build
running build_ext
building 'pyodbc' extension
creating build
creating build/temp.linux-x86_64-2.7
creating build/temp.linux-x86_64-2.7/src
gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -DPYODBC_VERSION=4.0.17 -DSQL_WCHART_CONVERT=1 -I/usr/local/include/python2.7 -c src/cursor.cpp -o build/temp.linux-x86_64-2.7/src/cursor.o -Wno-write-strings
unable to execute 'gcc': No such file or directory
error: command 'gcc' failed with exit status 1
----------------------------------------
Running setup.py clean for pyodbc
Failed to build pyodbc
Installing collected packages: pyodbc
Running setup.py install for pyodbc: started
Running setup.py install for pyodbc: finished with status 'error'
Complete output from command /usr/local/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-EfWsmy/pyodbc/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-BV4sRM-record/install-record.txt --single-version-externally-managed --compile:
running install
running build
running build_ext
building 'pyodbc' extension
creating build
creating build/temp.linux-x86_64-2.7
creating build/temp.linux-x86_64-2.7/src
gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -DPYODBC_VERSION=4.0.17 -DSQL_WCHART_CONVERT=1 -I/usr/local/include/python2.7 -c src/cursor.cpp -o build/temp.linux-x86_64-2.7/src/cursor.o -Wno-write-strings
unable to execute 'gcc': No such file or directory
error: command 'gcc' failed with exit status 1
----------------------------------------
Command "/usr/local/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-EfWsmy/pyodbc/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-BV4sRM-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-EfWsmy/pyodbc/
The command '/bin/sh -c pip install -r requirements.txt' returned a non-zero code: 1
【问题讨论】:
错误信息是什么?连接被拒绝? ...? 发布您的代码和完整的异常详细信息以及您如何启动容器 【参考方案1】:需要运行:
sudo apt-get install gcc
需要添加一个odbcinst.ini文件,其中包含:
[FreeTDS]Description=FreeTDS Driver Driver=/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so Setup=/usr/lib/x86_64-linux-gnu/odbc/libtdsS.so
需要在 docker 文件中添加以下内容
ADD odbcinst.ini /etc/odbcinst.ini
RUN apt-get update
RUN apt-get install -y tdsodbc unixodbc-dev
RUN apt install unixodbc-bin -y
RUN apt-get clean -y
需要将.py中的连接改为
connection = pyodbc.connect('Driver=FreeTDS;'
'Server=xxxxx;'
'Database=DCMM;'
'UID=xxxxx;'
'PWD=xxxxx')
现在容器编译,并从 SQL 服务器获取数据
【讨论】:
仍然面临问题 ('01000', "[01000] [unixODBC][Driver Manager]Can't open lib 'FreeTDS' : file not found 这也没有解决我的问题。仍然面临与 Apurva jain 相同的问题。 “sudo apt install build-essential”,以防“sudo apt-get install gcc”给你一个未找到的错误【参考方案2】:最近通过这个,我发现有必要额外包含以下行(注意它没有这一步就无法构建):
RUN apt-get install --reinstall build-essential -y
完整的 Dockerfile 如下所示:
# parent image
FROM python:3.7-slim
# install FreeTDS and dependencies
RUN apt-get update \
&& apt-get install unixodbc -y \
&& apt-get install unixodbc-dev -y \
&& apt-get install freetds-dev -y \
&& apt-get install freetds-bin -y \
&& apt-get install tdsodbc -y \
&& apt-get install --reinstall build-essential -y
# populate "ocbcinst.ini"
RUN echo "[FreeTDS]\n\
Description = FreeTDS unixODBC Driver\n\
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so\n\
Setup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so" >> /etc/odbcinst.ini
# install pyodbc (and, optionally, sqlalchemy)
RUN pip install --trusted-host pypi.python.org pyodbc==4.0.26 sqlalchemy==1.3.5
# run app.py upon container launch
CMD ["python", "app.py"]
这是一种通过 sqlalchemy(假设端口为 1433)在 app.py 中实际建立连接的方法:
import sqlalchemy as sa
args = (username, password, server, database)
connstr = "mssql+pyodbc://:@/?driver=FreeTDS&port=1433&odbc_options='TDS_Version=8.0'"
engine = sa.create_engine(connstr.format(*args))
【讨论】:
odbc.ini 怎么样?我也需要填充它吗? 您可以按照以下内容添加一些内容... # Populate "odbc.ini" RUN echo "[根据 Kåre Rasmussen 的回答,这里有一个完整的 dockerfile 供进一步使用。
确保根据您的架构编辑最后两行!它们应该反映 libtdsodbc.so 和 libtdsS.so 的实际路径。
如果您不确定 libtdsodbc.so 和 libtdsS.so 的路径,请尝试 dpkg --search libtdsodbc.so
和 dpkg --search libtdsS.so
。
FROM python:3
#Install FreeTDS and dependencies for PyODBC
RUN apt-get update && apt-get install -y tdsodbc unixodbc-dev \
&& apt install unixodbc-bin -y \
&& apt-get clean -y
RUN echo "[FreeTDS]\n\
Description = FreeTDS unixODBC Driver\n\
Driver = /usr/lib/arm-linux-gnueabi/odbc/libtdsodbc.so\n\
Setup = /usr/lib/arm-linux-gnueabi/odbc/libtdsS.so" >> /etc/odbcinst.ini
然后,安装 PyODBC,复制您的应用并运行它。
【讨论】:
安装后在 Dockerfile 中添加“RUN ls -l /usr/lib/x86_64-linux-gnu/odbc/”行将列出目录,您是否可以确认您的文件是否存在或不是。【参考方案4】:为了解决这个问题,我还必须在 dockerfile 中添加以下 2 行:
RUN echo MinProtocol = TLSv1.0 >> /etc/ssl/openssl.cnf
RUN echo CipherString = DEFAULT@SECLEVEL=1 >> /etc/ssl/openssl.cnf
【讨论】:
这也解决了我的问题,在 docker 映像之外一切正常,甚至sqlcmd
,但在 docker 映像内部,只有这 2 个配置工作正常!非常感谢!【参考方案5】:
如何为pyodbc
安装必要的依赖项与 linux 发行版及其版本有关(在 docker 的情况下,这是您的 docker 镜像的基础镜像)。如果上述方法都不适合您,您可以通过在 docker 容器实例中尝试找出命令。
首先,exec进入docker容器
docker exec -it <container id> bash
试试你的 linux 的various ways to get the distribution name and version。然后在Install the Microsoft ODBC driver for SQL Server (Linux)尝试不同的指令
这里是一个基于 Debian 9 的镜像的工作示例,完全按照文档说明导出。
# Install pyodbc dependencies
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/debian/9/prod.list > /etc/apt/sources.list.d/mssql-release.list
RUN apt-get update
RUN ACCEPT_EULA=Y apt-get -y install msodbcsql17
RUN apt-get -y install unixodbc-dev
RUN pip install pyodbc
【讨论】:
【参考方案6】:我无法使用上述所有解决方案,我一直在保留与 pyodbc 包有关的各种错误,特别是:
ImportError: libodbc.so.2: cannot open shared object file: No such file or directory.
我最终得到了另一个解决方案,它专门为 Ubuntu 18.04 Docker 映像定义了 ODBC SQL Server 驱动程序,在本例中为 ODBC Driver 17 for SQL Server。在我的特定用例中,我需要通过Flask SQLAlchemy 连接到Azure 上的 mysql 数据库服务器,但后者对于 Docker 配置不是必需的。
Dockerfile,最重要的部分是添加 Microsoft 存储库并安装 msodbcsql17 和 unixodbc-dev:
# Ubuntu 18.04 base with Python runtime and pyodbc to connect to SQL Server
FROM ubuntu:18.04
WORKDIR /app
# apt-get and system utilities
RUN apt-get update && apt-get install -y \
curl apt-utils apt-transport-https debconf-utils gcc build-essential g++-5\
&& rm -rf /var/lib/apt/lists/*
# adding custom Microsoft repository
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/ubuntu/18.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
# install SQL Server drivers
RUN apt-get update && ACCEPT_EULA=Y apt-get install -y msodbcsql17 unixodbc-dev
# install SQL Server tools
RUN apt-get update && ACCEPT_EULA=Y apt-get install -y mssql-tools
RUN echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
RUN /bin/bash -c "source ~/.bashrc"
# python libraries
RUN apt-get update -y && \
apt-get install -y python3-pip python3-dev
# install necessary locales, this prevents any locale errors related to Microsoft packages
RUN apt-get update && apt-get install -y locales \
&& echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \
&& locale-gen
# copy requirements and install packages, I added this for general use
COPY ./requirements.txt > ./requirements.txt
RUN pip3 install -r ./requirements.txt
# you can also use regular install of the packages
RUN pip3 install pyodbc SQLAlchemy
# and if you are also planning to use Flask and Flask-SQLAlchemy
Run pip3 install Flask Flask-SQLAlchemy
COPY ..
# run your app via entrypoint or change the CMD command to your regular command
COPY docker-entrypoint.sh wsgi.py ./
CMD ["./docker-entrypoint.sh"]
这应该在 Docker 中构建没有任何错误。
我的数据库网址如下所示:
import urllib.parse
# name the sepcific ODBC driver by version number, we installed msodbcsql17
params = urllib.parse.quote_plus("DRIVER=ODBC Driver 17 for SQL Server;SERVER=<your.database.windows.net>;DATABASE=<your-db-name>;UID=<username>;PWD=<password>")
db_uri = "mssql+pyodbc:///?odbc_connect=PARAMS".format(PARAMS=params)
如果您使用的是 Flask-SQLAlchemy,那么您的应用配置应该包含以下内容:
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_DATABASE_URI"] = db_uri # from above
编码愉快!
【讨论】:
【参考方案7】:我在 GitHub 上创建了一个关于如何执行此操作的 Gist。我希望它有所帮助。我必须从我在不同资源上找到的东西拼凑起来。
https://gist.github.com/joshatxantie/4bcf5d0243fba63845fce7cc40365a3a
祝你好运!
【讨论】:
这是唯一对我有用的解决方案,谢谢【参考方案8】:我通过使用 pypyodbc 而不是 pyodbc 解决了这个问题。
pip install pypyodbc==1.3.5
https://pypi.org/project/pypyodbc/
在这里找到提示: https://github.com/Azure/azure-functions-python-worker/issues/249
【讨论】:
以上是关于使用 pyodbc 将 docker python 连接到 SQL 服务器的主要内容,如果未能解决你的问题,请参考以下文章
使用 pyodbc 将 Python 连接到 MS SQL Server
使用 pyodbc 将 SQL Server 连接到 Python 3