使用pyodbc将docker python连接到SQL服务器

Kår*_*sen 12 pyodbc docker dockerfile

我正在尝试连接在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"]
Run Code Online (Sandbox Code Playgroud)

requirements.TXT

pyodbc
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

建造容器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
Run Code Online (Sandbox Code Playgroud)

Mar*_*son 21

最近我发现有必要额外包含以下行(请注意,如果没有这一步,它不会构建):

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"]
Run Code Online (Sandbox Code Playgroud)

这是通过 sqlalchemy(并假设端口 1433)在 app.py 中实际建立连接的一种方法:

# 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"]
Run Code Online (Sandbox Code Playgroud)

  • 您可以添加以下内容... # Populate "odbc.ini" RUN echo "[<your_db_name>]\n\ Driver = FreeTDS\n\ Address = <hostname_here>\n\ Port = {your_db_port[通常 1433]}\n\ Database = <your_db_name>\n\ TDS_Version = 8.0\n" >> /etc/odbc.ini ...原则上所有这些信息都可以传递到 pyodbc 连接字符串中,所以我相信这一步并不是绝对必要的。 (2认同)
  • 但是,我收到以下错误: pyodbc.OperationalError: ('08S01', '[08S01] [FreeTDS][SQL Server]无法连接: Adaptive Server 不可用或不存在 (20009) (SQLDriverConnect)')。你知道为什么吗? (2认同)

Kår*_*sen 14

需要运行:

sudo apt-get install gcc
Run Code Online (Sandbox Code Playgroud)

需要添加包含以下内容的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
Run Code Online (Sandbox Code Playgroud)

需要添加到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
Run Code Online (Sandbox Code Playgroud)

需要在.py中更改连接

connection = pyodbc.connect('Driver={FreeTDS};'
                            'Server=xxxxx;'
                            'Database=DCMM;'
                            'UID=xxxxx;'
                            'PWD=xxxxx')
Run Code Online (Sandbox Code Playgroud)

现在容器编译,并从SQL服务器获取数据

  • 仍然面临问题('01000',“[01000] [unixODBC][驱动程序管理器]无法打开 lib 'FreeTDS':找不到文件 (10认同)

mar*_*use 9

我无法使用上述所有解决方案,我保留了与 pyodbc 包相关的各种错误,特别是:

ImportError: libodbc.so.2: 无法打开共享对象文件: 没有这样的文件或目录。

我最终得到了另一个解决方案,专门为 Ubuntu 18.04 Docker 映像定义 ODBC SQL Server 驱动程序,在本例中为 ODBC Driver 17 for SQL Server。在我的特定用例中,我需要通过Flask SQLAlchemy连接到Azure上的 MySQL 数据库服务器,但后者并不是 Docker 配置所必需的。

Dockerfile,最重要的部分是添加 Microsoft 存储库并安装msodbcsql17unixodbc-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"]
Run Code Online (Sandbox Code Playgroud)

这应该在 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)
Run Code Online (Sandbox Code Playgroud)

如果您使用 Flask-SQLAlchemy,您的应用程序配置应该包含如下内容:

app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_DATABASE_URI"] = db_uri  # from above
Run Code Online (Sandbox Code Playgroud)

快乐编码!


D_S*_*ite 8

如何安装必要的依赖项pyodbc与linux发行版及其版本有关(在docker情况下,即是docker镜像的基础镜像)。如果以上方法都不适合您,您可以通过在 docker 容器实例中尝试来找出命令。

首先,exec进docker容器

docker exec -it <container id> bash
Run Code Online (Sandbox Code Playgroud)

尝试各种方法来获取Linux 的发行版名称和版本。然后尝试安装适用于 SQL Server (Linux) 的 Microsoft ODBC 驱动程序中的不同说明

这是基于 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
Run Code Online (Sandbox Code Playgroud)


Pho*_*log 5

根据KåreRasmussen的回答,这是一个完整的dockerfile供进一步使用。

确保根据您的体系结构编辑最后两行!它们应反映libtdsodbc.so和libtdsS.so的实际路径。

如果不确定libtdsodbc.so和libtdsS.so的路径,请尝试dpkg --search libtdsodbc.sodpkg --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
Run Code Online (Sandbox Code Playgroud)

然后,安装PyODBC,复制您的应用程序并运行它。

  • 安装后在 Dockerfile 中添加“RUN ls -l /usr/lib/x86_64-linux-gnu/odbc/”行将列出目录,您可以确认文件是否存在。 (2认同)

小智 5

我在 GitHub 上创建了一个关于如何执行此操作的要点。我希望它有帮助。我必须将在不同资源中找到的内容拼凑起来。

https://gist.github.com/joshatxantie/4bcf5d0243fba63845fce7cc40365a3a

祝你好运!