在Docker容器内使用FreeTDS无法连接到Microsoft SQL Server

7

我希望使用Docker for Windows在我们公司的网络上托管Shiny应用程序。

我该如何设置Docker、odbc.ini、odbcinst.ini、freetds.conf或其他文件,以便我的Shiny应用程序可以从内部Microsoft SQL Server(2016)数据库查询数据?数据库服务器未在运行Docker容器的同一台机器上。

我不知道是否需要更新FreeTDS版本,或者我是否已经错误配置了其中一个文件。我尝试在所有文件中使用服务器的IP地址而不是sql-server.host.com,但是仍然收到下面相同的错误消息。

$ tsql -C 输出:

Compile-time settings (established with the "configure" script)
                            Version: freetds v1.00.104
             freetds.conf directory: /etc/freetds
     MS db-lib source compatibility: no
        Sybase binary compatibility: yes
                      Thread safety: yes
                      iconv library: yes
                        TDS version: 4.2
                              iODBC: no
                           unixodbc: yes
              SSPI "trusted" logins: no
                           Kerberos: yes
                            OpenSSL: no
                             GnuTLS: yes
                               MARS: no

$ odbcinst -j 输出:

unixODBC 2.3.6
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /root/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8

$ cat etc/odbcinst.ini 输出:

[FreeTDS]
Description = FreeTDS unixODBC Driver
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so

$ cat etc/odbc.ini 输出:

[sql-server]
driver = FreeTDS
server = sql-server.host.com
port = 1433
TDS_Version = 4.2

$ cat etc/freetds/freetds.conf 输出:

[sql-server]
host = sql-server.host.com
port = 1433
tds version = 4.2

R命令出现错误:

con <- dbConnect(odbc::odbc(),
          driver = "FreeTDS",
          server = "sql-server.host.com",
          port = 1433,
          database = "database name",
          TDS_Version = 4.2)

错误:

Error: nanodbc/nanodbc.cpp:950: 08001: [FreeTDS][SQL Server]Unable to connect to data source 
Execution halted

Docker文件:

# Install R version 3.5.3
FROM r-base:3.5.3

# Install Ubuntu packages
RUN apt-get update && apt-get install -y \
    sudo \
    gdebi-core \
    pandoc \
    pandoc-citeproc \
    libcurl4-gnutls-dev \
    libcairo2-dev/unstable \
    libxt-dev \
    libssl-dev \
    unixodbc unixodbc-dev \
    freetds-bin freetds-dev tdsodbc

# Edit odbc.ini, odbcinst.ini, and freetds.conf files
RUN echo "[sql-server]\n\
host = sql-server.host.com\n\
port = 1433\n\
tds version = 4.2" >> /etc/freetds.conf

RUN echo "[FreeTDS]\n\
Description = FreeTDS unixODBC Driver\n\
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so" >> /etc/odbcinst.ini

RUN echo "[sql-server]\n\
driver = FreeTDS\n\
server = sql-server.host.com\n\
port = 1433\n\
TDS_Version = 4.2" >> /etc/odbc.ini

# Install R packages that are required
RUN R -e "install.packages(c('shiny', 'DBI', 'odbc'), repos='http://cran.rstudio.com/')"

# copy the app to the image
RUN mkdir /root/shiny_example
COPY app /root/shiny_example

COPY Rprofile.site /usr/lib/R/etc/

# Make the ShinyApp available at port 801
EXPOSE 801

CMD ["R", "-e", "shiny::runApp('/root/shiny_example')"]

Docker构建和运行命令:

docker build . -t shiny_example
docker run -it --network=host -p 801:801 shiny_example

请注意,以下R代码在我的Windows机器上运行Docker容器,并且我可以成功地查询数据库:

library(DBI)
con <- dbConnect(odbc::odbc(),
          driver = "SQL server",
          server = "sql-server.host.com")

$ isql -v sql-server 输出:

[S1000][unixODBC][FreeTDS][SQL Server]Unable to connect to data source
[01000][unixODBC][FreeTDS][SQL Server]Unknown host machine name.
[ISQL]ERROR: Could not SQLConnect

$ tsql -S sql-server 输出:

locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Error 20013 (severity 2):
        Unknown host machine name.
There was a problem connecting to the server

看起来你需要指定用户名和密码,如果它们还没有在客户端上指定。 - Renat
我需要在 R 代码中指定用户名和密码吗?在我的 Windows 机器上,我不需要指定用户名和密码,所以我猜它使用的是我的 Windows 登录用户名和密码,这正确吗? - Giovanni Colitti
是的,默认情况下,SQL Server 使用 Windows 登录用户通过 NTLM 进行身份验证,在 Linux 上没有 NTLM。我不熟悉如何从 Linux 连接到 SQL Server,但在我看来,用户名/密码需要在 odbc.inifreetds.conf 中。 - Renat
在我的Windows机器上,我使用Windows身份验证。我需要请求DBA团队为我在SQL Server中设置不同种类的身份验证,以使我能够从Docker容器内访问数据库服务器吗?我甚至不知道我的用户名或密码应该是什么。 - Giovanni Colitti
也许我需要按照此处所述使用SQL Server身份验证进行登录:Microsoft Docs - Giovanni Colitti
1个回答

3

看起来你是正确的,但可能忽略了一点。我之前也遇到过类似的问题,不过我成功解决了!

python+mssqlserver+pymssql+docker(unbuntu16.04基础镜像)

在未修复结尾的情况下,当我运行我的代码(使用 pymssql)时,会出现这个错误

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "src/pymssql.pyx", line 645, in pymssql.connect
pymssql.InterfaceError: Connection to the database failed for an unknown reason.

按照的方法创建了 3 个文件并将图像复制进去!

  • 使用 myserver.orgName.com 连接 MSsql 服务器。 docker/odbcinst.ini
[FreeTDS]
Description = v0.91 with protocol v7.3
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so

docker/odbc.ini

[myserverdsn]
Driver = FreeTDS
Server = myserver.orgName.com
Port = 1433
TDS_Version = 7.3

docker/freetds.conf

[global]
    # TDS protocol version, use:
    # 7.3 for SQL Server 2008 or greater (tested through 2014)
    # 7.2 for SQL Server 2005
    # 7.1 for SQL Server 2000
    # 7.0 for SQL Server 7
    tds version = 7.2
    port = 1433

    # Whether to write a TDSDUMP file for diagnostic purposes
    # (setting this to /tmp is insecure on a multi-user system)
;   dump file = /tmp/freetds.log
;   debug flags = 0xffff

    # Command and connection timeouts
;   timeout = 10
;   connect timeout = 10

    # If you get out-of-memory errors, it may mean that your client
    # is trying to allocate a huge buffer for a TEXT field.
    # Try setting 'text size' to a more reasonable limit
    text size = 64512

# A typical Microsoft server
[myserverdsn]
    host = myserver.orgName.com
    port = 1433
    tds version = 7.3

Dockerfile内容

RUN apt-get -y install unixodbc unixodbc-dev freetds-dev freetds-bin tdsodbc 

COPY freetds.conf /etc/freetds/freetds.conf
COPY odbc.ini /etc/odbc.ini
COPY odbcinst.ini /etc/odbcinst.ini

测试能正常工作的 Python 代码:

python 
>>> import pymssql
>>> conn = pymssql.connect(server = 'myserver.orgName.com',
                   user = 'myusername',
                      password = 'mypassword',
                      database= 'mydbname')

无故障地运行!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接