Docker 容器:无法按名称连接到 SQL 服务器
Docker Container: Unable to connect to SQL Server by name
我在同一网络上创建了两个容器,其中一个作为 Sql 服务器实例 运行。在另一个容器中(使用 SQL 工具)我可以使用 IP 地址连接到 SQL,但是如果我切换到机器名称它会失败。
我已经尝试对机器执行 ping 操作,dns 正在解析正确的 IP,我也尝试了 dnslookup,它也能正常工作。有人知道如何解决这个问题吗?
完整测试场景:
已创建新网络
docker network create --driver=bridge specsnet
运行 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
运行 带有 SQL 工具的新容器(用于测试连接)
docker run -it --net=specsnet --rm --entrypoint "bash" mcr.microsoft.com/mssql-tools:latest
加载了一些用于故障排除的工具(进入 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
使用 IP 测试连接(成功 - IP 为 172.18.0.2)
sqlcmd -S tcp:172.18.0.2,1433 -U sa -P 'Password!123456'
使用名称测试连接(失败)
sqlcmd -S tcp:TestDBServer,1433 -U sa -P 'Password!123456'
您的 sqlcmd
的 TestDBServer
部分引用了所谓的 Server Alias. These server aliases are not accessible due to the way you have set up the Docker networking currently. If you switch to Docker compose 来为您设置网络,它应该可以工作。
另一种方法是 --link
将有问题的容器放在一起。
因此,正如 Bjoern 所建议的那样,我创建了一个 docker 撰写文件,在进行了一些测试后,我意识到问题并未得到解决。
然后我开始操作文件,调整属性,发现问题出在 SQL 容器名称上(容器名称有大写字母) .我将 SQL 容器名称设置为 "testdbserver" 并且一切正常。
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
在 Bash 模式下启动 SQL 工具容器
docker-compose run sqltools bash
执行SQL测试连接(现在有效)
sqlcmd -S tcp:testdbserver,1433 -U sa -P 'Password!123456'
我在使用网关和微服务时遇到了同样的问题:
- 创建网络:
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"}
编辑:
经过更多的挖掘,我发现如果名称(或别名)包含下划线字符,则使用容器名称的通信不起作用。因此,如果您遇到问题,请检查您的容器名称。
我在同一网络上创建了两个容器,其中一个作为 Sql 服务器实例 运行。在另一个容器中(使用 SQL 工具)我可以使用 IP 地址连接到 SQL,但是如果我切换到机器名称它会失败。
我已经尝试对机器执行 ping 操作,dns 正在解析正确的 IP,我也尝试了 dnslookup,它也能正常工作。有人知道如何解决这个问题吗?
完整测试场景:
已创建新网络
docker network create --driver=bridge specsnet
运行 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
运行 带有 SQL 工具的新容器(用于测试连接)
docker run -it --net=specsnet --rm --entrypoint "bash" mcr.microsoft.com/mssql-tools:latest
加载了一些用于故障排除的工具(进入 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
使用 IP 测试连接(成功 - IP 为 172.18.0.2)
sqlcmd -S tcp:172.18.0.2,1433 -U sa -P 'Password!123456'
使用名称测试连接(失败)
sqlcmd -S tcp:TestDBServer,1433 -U sa -P 'Password!123456'
您的 sqlcmd
的 TestDBServer
部分引用了所谓的 Server Alias. These server aliases are not accessible due to the way you have set up the Docker networking currently. If you switch to Docker compose 来为您设置网络,它应该可以工作。
另一种方法是 --link
将有问题的容器放在一起。
因此,正如 Bjoern 所建议的那样,我创建了一个 docker 撰写文件,在进行了一些测试后,我意识到问题并未得到解决。
然后我开始操作文件,调整属性,发现问题出在 SQL 容器名称上(容器名称有大写字母) .我将 SQL 容器名称设置为 "testdbserver" 并且一切正常。
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
在 Bash 模式下启动 SQL 工具容器
docker-compose run sqltools bash
执行SQL测试连接(现在有效)
sqlcmd -S tcp:testdbserver,1433 -U sa -P 'Password!123456'
我在使用网关和微服务时遇到了同样的问题:
- 创建网络:
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"}
编辑: 经过更多的挖掘,我发现如果名称(或别名)包含下划线字符,则使用容器名称的通信不起作用。因此,如果您遇到问题,请检查您的容器名称。