使用容器名称从主机访问docker容器

我正在开发一个服务,并使用泊坞窗撰写旋转服务,如postgres,redis,elasticsearch。 我有一个基于RubyOnRails的Web应用程序,并从所有这些服务中读写。

这是我docker-compose.yml

 version: '2' services: redis: image: redis:2.8 networks: - frontapp elasticsearch: image: elasticsearch:2.2 networks: - frontapp postgres: image: postgres:9.5 environment: POSTGRES_USER: elephant POSTGRES_PASSWORD: smarty_pants POSTGRES_DB: elephant volumes: - /var/lib/postgresql/data networks: - frontapp networks: frontapp: driver: bridge 

我可以ping这个networking中的容器

 $ docker-compose run redis /bin/bash root@777501e06c03:/data# ping postgres PING postgres (172.20.0.2): 56 data bytes 64 bytes from 172.20.0.2: icmp_seq=0 ttl=64 time=0.346 ms 64 bytes from 172.20.0.2: icmp_seq=1 ttl=64 time=0.047 ms ... 

到现在为止还挺好。 现在我想在我的主机上运行rails应用程序的ruby,但能够访问postgres实例的URL像postgresql://username:password@postgres/database目前是不可能的

 $ ping postgres ping: unknown host postgres 

我可以在docker中看到我的networking

 $ docker network ls NETWORK ID NAME DRIVER ac394b85ce09 bridge bridge 0189d7e86b33 elephant_default bridge 7e00c70bde3b elephant_frontapp bridge a648554a72fa host host 4ad9f0f41b36 none null 

我可以看到一个界面

 $ ifconfig br-0189d7e86b33 Link encap:Ethernet HWaddr 02:42:76:72:bb:c2 inet addr:172.18.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:76ff:fe72:bbc2/64 Scope:Link UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:36 errors:0 dropped:0 overruns:0 frame:0 TX packets:60 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:2000 (2.0 KB) TX bytes:8792 (8.7 KB) br-7e00c70bde3b Link encap:Ethernet HWaddr 02:42:e7:d1:fe:29 inet addr:172.20.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:e7ff:fed1:fe29/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1584 errors:0 dropped:0 overruns:0 frame:0 TX packets:1597 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:407137 (407.1 KB) TX bytes:292299 (292.2 KB) ... 

但我不知道下一步该怎么做。 我试着用/etc/resolv.conf来玩,主要是使用nameserver指令,但是没有任何效果。

我将不胜感激任何帮助build议如何正确configuration此设置。

UPDATE

浏览互联网资源后,我设法分配静态IP地址框。 现在,我继续发展就够了。 这是我目前docker-compose.yml

 version: '2' services: redis: image: redis:2.8 networks: frontapp: ipv4_address: 172.25.0.11 elasticsearch: image: elasticsearch:2.2 networks: frontapp: ipv4_address: 172.25.0.12 postgres: image: postgres:9.5 environment: POSTGRES_USER: elephant POSTGRES_PASSWORD: smarty_pants POSTGRES_DB: elephant volumes: - /var/lib/postgresql/data networks: frontapp: ipv4_address: 172.25.0.10 networks: frontapp: driver: bridge ipam: driver: default config: - subnet: 172.25.0.0/16 gateway: 172.25.0.1 

有一个开源的应用程序解决了这个问题,它被称为DNS代理服务器

这是一个解决容器主机名的DNS服务器,如果找不到具有该主机名的主机名,然后从互联网上解决它

启动DNS服务器

 $ docker run --hostname dns.mageddo --name dns-proxy-server -p 5380:5380 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /etc/resolv.conf:/etc/resolv.conf \ defreitas/dns-proxy-server 

它将自动设置为您的默认DNS(并在停止时恢复到原始状态)

开始你的容器testing

 docker-compose up 

泊坞窗,compose.yml

 version: '2' services: redis: container_name: redis image: redis:2.8 hostname: redis.dev.intranet network_mode: bridge # that way he can solve others containers names even inside, solve elasticsearch, for example elasticsearch: container_name: elasticsearch image: elasticsearch:2.2 hostname: elasticsearch.dev.intranet 

现在解决你的容器主机名

从主机

 $ nslookup redis.dev.intranet Server: 172.17.0.2 Address: 172.17.0.2#53 Non-authoritative answer: Name: redis.dev.intranet Address: 172.21.0.3 

从另一个容器

 $ docker exec -it redis ping elasticsearch.dev.intranet PING elasticsearch.dev.intranet (172.21.0.2): 56 data bytes 

以及它解决互联网主机名称

 $ nslookup google.com Server: 172.17.0.2 Address: 172.17.0.2#53 Non-authoritative answer: Name: google.com Address: 216.58.202.78 

docker集装箱的主机名不能从外面看到。 你可以做的是给容器分配一个名称,并通过名称访问容器。 如果你链接2个容器,比如container1和container2,那么docker负责在container1中写入container2的IP和主机名。 但是在你的情况下,你的应用程序正在主机中运行。

要么

你知道容器的IP。 所以在你的主机的/ etc / hosts中你可以添加$ IP $ hostanameof容器

如果您只是在本地使用docker-compose setup,则可以将容器中的端口映射到您的主机

 elasticsearch: image: elasticsearch:2.2 ports: - 9300:9300 - 9200:9200 

然后使用web应用程序中的localhost:9300(或9200,取决于协议)访问Elasticsearch。

更复杂的解决scheme是运行你自己的解决容器名称的DNS。 我认为这个解决scheme更接近你所要求的。 在本地运行kubernetes时,我已经预先使用了skydns。

那里有几个选项。 看看https://github.com/gliderlabs/registrator和https://github.com/jderusse/docker-dns-gen 。 我没有尝试过,但是你可以像上一个例子中的弹性端口一样将dns端口映射到主机,然后将localhost添加到resolv.conf中,以便能够parsing你的容器名称主办。

Aditya是正确的。 在你的情况下,最简单的是在/etc/hosts硬编码你的主机名/ IP映射

然而,这种方法的问题是你不控制你的postgres机器的私人IP地址。 每次启动一个新的容器时,IP地址都会改变,所以你需要更新你的/ etc / hosts文件。

如果这是一个问题,我build议你阅读这个博客文章,解释如何强制一个容器得到一个特定的IP地址:

https://xand.es/2016/05/09/docker-with-known-ip/

有两个解决scheme(除了/etc/hosts ) 在这里和这里描述

我用Python编写了我自己的解决scheme,并将其实现为服务,以提供从容器主机名到其IP的映射。 这里是: https : //github.com/nicolai-budico/dockerhosts

它使用参数--hostsdir=/var/run/docker-hosts启动dnsmasq,并在每次运行容器列表发生更改时更新文件/var/run/docker-hosts/hosts 。 一旦文件/var/run/docker-hosts/hosts被更改,dnsmasq会自动更新其映射,容器将在一秒之内变成主机名。

 $ docker run -d --hostname=myapp.local.com --rm -it ubuntu:17.10 9af0b6a89feee747151007214b4e24b8ec7c9b2858badff6d584110bed45b740 $ nslookup myapp.local.com Server: 127.0.0.53 Address: 127.0.0.53#53 Non-authoritative answer: Name: myapp.local.com Address: 172.17.0.2 

有安装和卸载脚本。 只有你需要的是让你的系统与这个dnsmasq实例交互。 我在systemd-resolved中注册了:

 $ cat /etc/systemd/resolved.conf [Resolve] DNS=127.0.0.54 #FallbackDNS= #Domains= #LLMNR=yes #MulticastDNS=yes #DNSSEC=no #Cache=yes #DNSStubListener=udp