Docker容器:无法按名称连接到SQL Server

时间:2018-06-05 17:23:25

标签: sql-server linux docker sqlcmd

我在同一个网络上创建了两个容器,其中一个作为运行的Sql Server实例。在另一个容器(使用SQL工具)中,我可以使用IP地址连接到SQL,但如果我切换到计算机名称则会失败。

我已经尝试过ping机器并且dns正在解决正确的IP,我也尝试过dnslookup并且它也正常工作。有谁知道如何解决这个问题?

完整的测试场景:

  1. 创建新网络

    docker network create --driver=bridge specsnet
    
  2. 运行SQL容器

    docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Password!123456' -p 1401:1433 -d --name=TestDBServer --net=specsnet --rm microsoft/mssql-server-linux:latest
    
  3. 使用SQL工具运行新容器(以测试连接)

    docker run -it --net=specsnet --rm --entrypoint "bash" mcr.microsoft.com/mssql-tools:latest
    
  4. 加载了一些故障排除工具(进入SQL工具容器)

    apt-get update | apt-get install telnet -y | apt-get install iputils-ping -y | apt-get install dnsutils -y | apt-get install nmap -y | apt-get install nano -y
    
  5. 使用IP测试连接(成功 - IP为172.18.0.2)

    sqlcmd -S tcp:172.18.0.2,1433 -U sa -P 'Password!123456'
    
  6. 使用名称测试连接(失败)

    sqlcmd -S tcp:TestDBServer,1433 -U sa -P 'Password!123456'
    

3 个答案:

答案 0 :(得分:0)

TestDBServer的{​​{1}}部分引用了所谓的Server Alias。由于您当前设置Docker网络的方式,无法访问这些服务器别名。如果您switch to Docker compose为您设置网络,它应该可以正常工作。

另一种方法是sqlcmd所讨论的容器。

答案 1 :(得分:0)

因为Bjoern建议我创建一个docker compose文件,在做了一些测试后我发现问题没有解决。

然后我开始操作文件,调整属性,发现问题出在SQL容器名称上(容器名称有大写字母)。我将SQL容器名称设置为“testdbserver”,一切正常。

  1. Docker撰写文件

    version: '2'
    services:
      testdbserver:
        image: microsoft/mssql-server-linux:latest
        ports:
          ["1401:1433"]
        environment:
          SA_PASSWORD: Password!123456
          ACCEPT_EULA: Y
        networks:
          - specsnet
    
      sqltools:
        image: mcr.microsoft.com/mssql-tools:latest
        depends_on:
          - testdbserver
        networks:
          - specsnet
    
    networks:
      specsnet:
        driver: bridge
        ipam:
         config:
           - subnet: 10.5.0.0/16
             gateway: 10.5.0.1
    
  2. 在Bash模式下启动SQL工具容器

    docker-compose run sqltools bash
    
  3. 执行SQL测试连接(立即使用

    sqlcmd -S tcp:testdbserver,1433 -U sa -P 'Password!123456'
    

答案 2 :(得分:0)

我在使用网关和微服务时遇到了同样的问题:

  • 创建网络:

docker network create mynet

  • 添加容器:
docker network connect mynet my-gateway
docker network connect mynet my_service_8080

这样做,我无法在使用容器名称时在两个容器之间进行通信。例如。连接到网关容器并对服务执行 curl 时:

curl -i http://my_service_8080:8080/management/info

HTTP/1.1 400
Transfer-Encoding: chunked
Date: Tue, 23 Feb 2021 12:51:47 GMT
Connection: close

在网上查了很多都没有结果后,我终于有了提供别名的想法:

docker network connect --alias gateway mynet my-gateway
docker network connect --alias myservice mynet my_service_8080

现在,我可以使用别名作为主机名成功地在容器之间进行通信:

curl -i http://myservice:8080/management/info

HTTP/1.1 200
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 23 Feb 2021 12:54:36 GMT

{"name":"myservice-app","description":"my service","version":"20210202"}

编辑: 经过更多的挖掘,我发现如果名称(或别名)包含下划线字符,则使用容器名称的通信不起作用。因此,如果您遇到问题,请检查您的容器名称。