我正在使用Docker 1.11.1和docker-compose 1.8.0-rc2。
在过去的好时光(去年),您可以设置docker-compose.yml
这样的文件:
app:
image: myapp
frontend:
image: myfrontend
links:
- app
然后启动这样的环境:
docker scale app=3 frontend=1
您的前端容器可以检查环境变量
对于名为APP_1_PORT
,APP_2_PORT
等的变量来发现
可用的后端主机并相应地配置自己。
时代变了。现在,我们这样做......
version: '2'
services:
app:
image: myapp
frontend:
image: myfrontend
links:
- app
...而不是环境变量,我们得到DNS。所以在里面
frontend
容器,我可以要求app_app_1
或app_app_2
或
app_app_3
并获取相应的IP地址。我也可以要求
app
并获取app_app_1
的地址。
但是如何发现所有可用的后端容器?一世
我想我可以循环getent hosts ...
直到它失败:
counter=1
while :; do
getent hosts app_$counter || break
backends="$backends app_$counter"
let counter++
done
但这看起来很丑陋而且很脆弱。
我听说过关于循环dns的传闻,但(a)似乎没有 在我的测试环境中发生,(b)不一定 如果您的前端需要同时连接到后端,请提供帮助。
简单的容器和服务发现如何在工作中发挥作用 现代Docker世界?
答案 0 :(得分:1)
Docker带有内置的名称服务器。默认情况下,可以通过127.0.0.11:53
访问该服务器。
默认情况下,每个容器在/etc/resolve.conf
中都有一个名称服务器条目,因此不需要从容器内指定名称服务器的地址。
这就是为什么您可以使用service
或stack_service_n
在网络中找到服务的原因。
如果您执行stack_service_n
,则将获得相应服务副本的地址。
如果您只要求service
码头工人将执行internal load balancing
。
使用群集时,docker将另外使用ingress network
提供external load balancing
,以允许从群集中的任何节点查询任何服务。
在将swarm用于deploy时,除非将endpointmode设置为dns roundrobin而不是vip,否则以下示例中所述的默认行为将无效。
endpoint_mode:vip-Docker为该服务分配一个虚拟IP(VIP),该虚拟IP充当客户端访问网络上服务的前端。 Docker在客户端和服务的可用工作节点之间路由请求,而无需客户端知道有多少节点正在参与服务或其IP地址或端口。 (这是默认设置。)
endpoint_mode:dnsrr-DNS循环(DNSRR)服务发现不使用单个虚拟IP。 Docker设置服务的DNS条目,以便对服务名称的DNS查询返回IP地址列表,并且客户端直接连接到其中之一。在想要使用自己的负载平衡器或混合Windows和Linux应用程序的情况下,DNS轮询很有用。
例如,从 dig / docker-compose.yml
部署三个副本version: '3.8'
services:
whoami:
image: "traefik/whoami"
deploy:
replicas: 3
回答您的问题如何找到所有容器。您可以使用诸如dig
或nslookup
之类的工具针对同一网络中的名称服务器进行DNS查找。
docker run --rm --network dig_default tutum/dnsutils dig whoami
; <<>> DiG 9.9.5-3ubuntu0.2-Ubuntu <<>> whoami
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58433
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;whoami. IN A
;; ANSWER SECTION:
whoami. 600 IN A 172.28.0.3
whoami. 600 IN A 172.28.0.2
whoami. 600 IN A 172.28.0.4
;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Mon Nov 16 22:36:37 UTC 2020
;; MSG SIZE rcvd: 90
如果您只对IP感兴趣,则可以提供+short
选项
docker run --rm --network dig_default tutum/dnsutils dig +short whoami
172.28.0.3
172.28.0.4
172.28.0.2
或寻找特定服务
docker run --rm --network dig_default tutum/dnsutils dig +short dig_whoami_2
172.28.0.4
接下来,通过curl测试内置的负载均衡器。重复此命令几次,然后观察主机名和IP地址的更改。
docker run --rm --network dig_default curlimages/curl -Ls http://whoami
Hostname: eedc94d45bf4
IP: 127.0.0.1
IP: 172.28.0.3
RemoteAddr: 172.28.0.5:43910
GET / HTTP/1.1
Host: whoami
User-Agent: curl/7.73.0-DEV
Accept: */*
这是10次curl中的主机名:
Hostname: eedc94d45bf4
Hostname: 42312c03a825
Hostname: 42312c03a825
Hostname: 42312c03a825
Hostname: eedc94d45bf4
Hostname: d922d86eccc6
Hostname: d922d86eccc6
Hostname: eedc94d45bf4
Hostname: 42312c03a825
Hostname: d922d86eccc6
这一切都说明了,这并不是报价现代服务发现中报价的真正方式。这就是traefik之类的项目开始发挥作用的地方。
如今,更多传统的代理很好地支持容器。例如,HAProxy在容器周围具有since 1.8的许多不错的功能,例如动态cookie,服务模板和docker名称服务器的一流集成。