允许docker容器连接到本地/主机postgres数据库

我最近一直在玩Docker和QGIS,并按照本教程中的说明安装了一个容器。

尽pipe我无法连接到包含我所有GIS数据的localhost postgres数据库,但一切正常。 我认为这是因为我的postgres数据库没有configuration为接受远程连接,并已编辑postgresconfiguration文件,以允许使用本文中的说明进行远程连接。

当我尝试连接到在Docker中运行QGIS的数据库时,仍然收到错误消息:无法连接到服务器: Connection refused Is the server running on host "localhost" (::1) and accepting TCP/IP connections to port 5433? postgres服务器正在运行,我编辑了我的pg_hba.conf文件,允许来自一系列IP地址(172.17.0.0/32)的连接。 我以前使用docker ps查询了docker容器的IP地址,尽pipeIP地址发生了变化,但它一直在172.17.0.x

任何想法,为什么我不能连接到这个数据库? 可能是我想象的很简单的东西!

我正在运行Ubuntu 14.04; Postgres 9.3

TL; DR

  1. 使用172.17.0.0/16作为IP地址范围,而不是172.17.0.0/32
  2. 不要使用localhost连接到主机上的PostgreSQL数据库,而是使用主机的IP。 要使容器保持可移植性,请使用--add-host=database:<host-ip>标志启动容器,并使用database作为连接到PostgreSQL的主机名。
  3. 确保PostreSQLconfiguration为侦听所有IP地址上的连接,而不仅仅是localhost 。 在PostgreSQL的configuration文件中查找设置listen_addresses ,通常在/etc/postgresql/9.3/main/postgresql.conf (信用于@DazmoNorton)中find。

长版

172.17.0.0/32不是一个IP地址范围 ,而是一个地址(名称为172.17.0.0 )。 Docker容器将不会获得分配的地址,因为它是Docker桥( docker0 )接口的networking地址。

当Docker启动时,它将创build一个新的桥接networking接口,在调用ip a时可以很容易地看到:

 $ ip a ... 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff inet 172.17.42.1/16 scope global docker0 valid_lft forever preferred_lft forever 

正如你所看到的,在我的情况下, docker0接口的IP地址为172.17.42.1 ,networking掩码为/16 (或255.255.0.0 )。 这意味着networking地址是172.17.0.0/16

IP地址是随机分配的,但没有任何额外的configuration,它将始终在172.17.0.0/16networking中。 对于每个Docker容器,将从该范围分配一个随机地址。

这意味着,如果要将所有可能的容器访问权限授予数据库,请使用172.17.0.0/16

Docker for Mac解决scheme

17.06开始

感谢@Birchlabs的评论,现在使用这个特殊的仅限于Mac的DNS名称变得更容易:

 docker run -e DB_PORT=5432 -e DB_HOST=docker.for.mac.localhost 

较旧的版本

@ helmbert的回答很好的解释了这个问题。 但是Docker for Mac 不会暴露桥接networking ,所以我不得不这样做来解决这个限制:

 $ sudo ifconfig lo0 alias 10.200.10.1/24 

打开/usr/local/var/postgres/pg_hba.conf并添加以下行:

 host all all 10.200.10.1/24 trust 

打开/usr/local/var/postgres/postgresql.conf并编辑更改listen_addresses

 listen_addresses = '*' 

重新加载服务并启动您的容器:

 $ PGDATA=/usr/local/var/postgres pg_ctl reload $ docker run -e DB_PORT=5432 -e DB_HOST=10.200.10.1 my_app 

这个解决方法的作用与@ helmbert的答案基本相同,但是使用连接到lo0而不是docker0networking接口的IP地址。

还有一件事是我的设置需要添加

 172.17.0.1 localhost 

/etc/hosts

所以Docker会指向172.17.0.1作为数据库主机名,而不是依靠一个改变的外层IP来查找数据库。 希望这可以帮助别人解决这个问题!

另一个解决scheme是服务量,您可以定义一个服务卷,并在该卷中挂载主机的PostgreSQL数据目录。 查看给定的撰写文件的细节。

 version: '2' services: db: image: postgres:9.6.1 volumes: - "/var/lib/postgresql/data:/var/lib/postgresql/data" ports: - "5432:5432" 

通过这样做,另一个PostgreSQL服务将在容器下运行,但使用主机PostgreSQL服务正在使用的相同的数据目录。