Подключите докер Python к SQL-серверу с помощью Pyodbc
Я пытаюсь подключить Python-скрипт Python, выполняющийся в Docker-контейнере, для входа в базу данных MSSQL. Я перепробовал все виды 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()
Сборка контейнерного докера 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
11 ответов
Нужно запустить:
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
нужно добавить следующий файл в докер
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-сервера.
Просматривая это недавно, я обнаружил, что необходимо дополнительно включить следующую строку (обратите внимание, что она не была построена без этого шага):
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"]
Вот один из способов установить соединение внутри app.py через sqlalchemy (при условии, что порт 1433):
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))
Ответ Кор Расмуссена помог мне собрать образ рабочего докера. Просто документирование всего изображения здесь для дальнейшего использования.
Обязательно отредактируйте последние две строки в соответствии с вашей архитектурой! Они должны отражать фактические пути к libtdsodbc.so и libtdsS.so.
Если вы не уверены в путях к libtdsodbc.so и libtdsS.so, попробуйте запустить dpgk --search libtdsodbc.so
а также dpgk --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, скопируйте свое приложение и запустите его.
Мне не удалось использовать все вышеперечисленные разрешения, я сохранял все виды ошибок, связанных с пакетом pyodbc, в частности:
ImportError: libodbc.so.2: невозможно открыть файл общих объектов: нет такого файла или каталога.
В итоге я получил другое разрешение, которое определяет драйвер ODBC SQL Server специально для образа Docker Ubuntu 18.04, в данном случае драйвер ODBC 17 для SQL Server. В моем конкретном случае использования мне нужно было установить соединение с моим сервером базы данных MySQL в Azure через Flask SQLAlchemy, но последнее не является необходимостью для конфигурации 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.
URL моей базы данных выглядел так:
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
Удачного кодирования!
Как установить необходимые зависимости для pyodbc
относится к дистрибутиву linux и его версии (в случае с докером это базовый образ вашего образа докера). Если ничего из вышеперечисленного не работает для вас, вы можете выяснить команды, попробовав экземпляр контейнера докеров.
Сначала выполните exec в контейнере докера.
docker exec -it <container id> bash
Попробуйте разные способы узнать название дистрибутива и версию вашего Linux. Затем попробуйте другие инструкции в разделе Установка драйвера Microsoft ODBC для 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
Я создал Gist на GitHub о том, как это сделать. Я надеюсь, что это помогает. Мне пришлось собрать воедино то, что я нашел на разных ресурсах.
https://gist.github.com/joshatxantie/4bcf5d0243fba63845fce7cc40365a3a
Удачи!
Чтобы решить эту проблему, мне также пришлось добавить следующие 2 строки в файл dockerfile:
RUN echo MinProtocol = TLSv1.0 >> /etc/ssl/openssl.cnf
RUN echo CipherString = DEFAULT@SECLEVEL=1 >> /etc/ssl/openssl.cnf
Для тех, кто хотел сделать официальный подход Microsoft для установки драйвера odbc и использованияpython:slim
образ докера, вы можете использовать его как DockerFile:
FROM python:3.9-slim
RUN apt-get -y update && apt-get install -y curl gnupg
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
# download appropriate package for the OS version
# Debian 11
RUN curl https://packages.microsoft.com/config/debian/11/prod.list \
> /etc/apt/sources.list.d/mssql-release.list
RUN exit
RUN apt-get -y update
RUN ACCEPT_EULA=Y apt-get install -y msodbcsql18
Тогда для sqlalchemy это можно назвать:
con_str = f"mssql+pyodbc://{username}:{password}@{host}/{db}?" \
"driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes"
engine = create_engine(con_str)
Чтобы не было больше проблем, используйте библиотеку для pythonpymssql, для этого не нужно устанавливать драйвер.
pip install pymssql
import pymssql
conn = pymssql.connect(server, user, password, "tempdb")
cursor = conn.cursor(as_dict=True)
cursor.execute('SELECT * FROM persons WHERE salesrep=%s', 'John Doe')
for row in cursor:
print("ID=%d, Name=%s" % (row['id'], row['name']))
conn.close()
и работать в докере
Я исправил эту проблему, используя pypyodbc вместо pyodbc.
pip install pypyodbc==1.3.5
https://pypi.org/project/pypyodbc/
Нашел подсказку здесь:https://github.com/Azure/azure-functions-python-worker/issues/249
Чтобы заставить pyodbc работать с драйвером ODBC 17 для SQL Server в моем контейнере, я сделал следующее:
- Получите ключ microsoft.asc
Вот где его можно получить: https://packages.microsoft.com/keys/microsoft.asc .
- Обновите файл Docker, чтобы установить и распознать драйвер ODBC 17 для SQL Server и зависимостей.
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 \
&& apt-get install -y libltdl7 \
&& apt-get install -y libodbc1 \
&& apt-get install -y odbcinst \
&& apt-get install -y odbcinst1debian2 \
&& apt-get install -y locales-all
COPY microsoft.asc /usr/
RUN apt-get update
RUN apt-get update \
&& apt-get install -y curl apt-transport-https locales gnupg2 \
&& apt-key add /usr/microsoft.asc
RUN curl https://packages.microsoft.com/config/debian/11/prod.list > /etc/apt/sources.list.d/mssql-release.list
RUN exit
RUN apt-get update
RUN ACCEPT_EULA=Y apt-get install -y msodbcsql17
RUN ACCEPT_EULA=Y apt-get install -y mssql-tools
RUN echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
RUN echo "[ODBC Driver 17 for SQL Server]\n\
Description=Microsoft ODBC Driver 17 for SQL Server\n\
Driver=/opt/microsoft/msodbcsql17/lib64/libmsodbcsql-17.5.so.2.1\n\
UsageCount=1" >> /etc/odbcinst.ini