Docker和Consul:Pinging服务工作,但curl总是返回不能连接到主机错误

我正在尝试使用Docker部署多个服务,并使用Consul进行服务发现。 我已经通过各种指南和教程,我有以下bash脚本设置我的Docker容器:

export PRIVATE_IP=XXX.XXX.XXX.XXX export BRIDGE_IP=XXX.XXX.XXX.XXX docker run -d --name consul -h $HOSTNAME -p $PRIVATE_IP:8300:8300 -p $PRIVATE_IP:8301:8301 -p $PRIVATE_IP:8301:8301/udp -p $PRIVATE_IP:8302:8302 -p $PRIVATE_IP:8302:8302/udp -p $PRIVATE_IP:8400:8400 -p $PRIVATE_IP:8500:8500 -p $BRIDGE_IP:53:53/udp progrium/consul -server -advertise $PRIVATE_IP -bootstrap docker run -d --name registrator -v /var/run/docker.sock:/tmp/docker.sock -h $HOSTNAME gliderlabs/registrator consul://$PRIVATE_IP:8500 docker run -d --dns=$BRIDGE_IP --dns 8.8.8.8 --dns-search service.consul -p 3579:3579 --name service1 rcarrington/service1 docker run -d --dns=$BRIDGE_IP --dns 8.8.8.8 --dns-search service.consul -p 3580:3580 --name service2 rcarrington/service2 

只要我可以导航到Consul UI,看到所有节点都存在,我也可以导航到由service1和service2公开的服务。 有一件事我不确定的是,我不能将PRIVATE_IP和BRIDGE_IP设置为docker服务器公开的端口以外的任何东西。 该脚本只是错误,如果我尝试将BRIDGE_IP设置为172.17.42.1这显然是默认的。

问题是我希望我的服务能够相互沟通,而且他们似乎也不能这样做。 如果我从service2 ping service1然后我得到如下响应:

 # ping service1 # PING service1.service.consul (YYY.YYY.YYY.YYY): ZZ data bytes 

这似乎是正确的,但是当我尝试使用curl导航到它的服务我得到一个couldn't connect to host错误。 我已经尝试了主机名和IP地址(包括正确的端口)的每一个组合,没有运气。 可能奇怪的是,ping返回的IP地址不是上面脚本中使用的IP地址。

我在Windows 10上运行最新的Docker-Toolbox。我的服务容器正在运行mono并执行NancyFX self主机应用程序。

我假设我在bash脚本中做错了什么,但是我不知道是什么。 任何帮助将不胜感激。

尝试使用Docker撰写 。 它很容易使用,并具有内置的networking,因此容器可以相互通信。

一个简单的docker-compose.yml文件看起来像(未经testing):

 version: '2' services: consul: image: progrium/consul container_name: consul ports: - "8300:8300" - "8301:8301" - "8302:8302" - "8400:8400" - "8500:8500" registrator: image: gliderlabs/registrator container_name: registrator volumes: - /var/run/docker.sock:/tmp/docker.sock service1: image: rcarrington/service1 container_name: service1 ports: - "3579:3579" service2: image: rcarrington/service2 container_name: service2 ports: - "3580:3580" 

所有容器默认添加到networkingdocker_default ,并且可以通过container_name ping service1

如果你想创build自定义networking,你可以这样做:

 services: consul: ... networks: - consulnet registrator: ... networks: - consulnet networks: consulnet 

请参阅此链接了解有关Docker Compose中的联网的更多信息。

你正在使用桥梁networking的领事,这就是你面临这个问题的原因。 领事将分配一组不同的IP地址,如果其他服务不在,您将无法ping通。

 "TaggedAddresses": { "lan": "172.17.0.2", "wan": "172.17.0.2" }, 

您必须了解这样一个事实,即在您的应用程序扩展到多个容器/服务器时需要服务发现,如果您只想在一台主机上运行它以便进行testing,您实际上可以得到docker-compose的好处,将所有容器设置为一个网桥和服务发现将默认工作。

所以你需要使用–net = host来使用主机的networking运行你的consul容器,你会发现TaggedAddresses现在是主机的地址。

 curl http://localhost:8500/v1/catalog/nodes\?pretty [ { "ID": "5989c38f-298e-07f3-0069-d448dcc307d7", "Node": "consul-master", "Address": "10.11.14.171", "Datacenter": "dc1", "TaggedAddresses": { "lan": "10.11.14.171", "wan": "10.11.14.171" }, "Meta": {}, "CreateIndex": 5, "ModifyIndex": 6 }, 

你也可以深入研究它在DNS层面的工作。

 dig @127.0.0.1 -p 8600 stackoverflow.service.dc1.consul. ANY ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.55.amzn1 <<>> @127.0.0.1 -p 8600 stackoverflow.service.dc1.consul. ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 65131 ;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;stackoverflow.service.dc1.consul. IN ANY ;; ANSWER SECTION: stackoverflow.service.dc1.consul. 0 IN A 10.11.15.112 stackoverflow.service.dc1.consul. 0 IN A 10.11.14.34 stackoverflow.service.dc1.consul. 0 IN A 10.11.14.101 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Thu Jul 13 10:13:35 2017 ;; MSG SIZE rcvd: 90 

但是,在这里你会遇到curl的问题,因为dns转发不能在主机networking模式下使用–dns命令。 这不是一个真正的问题,因为你可以使用像dnsmasq之类的东西,或者已经有应用程序可以用来查找你的服务的包。 例如:您可以在您的nodejs应用程序中使用的consul-npm