当前位置: 首页>>技术教程>>正文


ubuntu – 允许Docker容器连接到本地/主机Postgres数据库

, , ,

问题描述

我最近一直在使用Docker和QGIS并按照this tutorial中的说明安装了一个容器。

尽管我无法连接到包含我的所有GIS数据的localhost postgres数据库,但一切工作都很好。我认为这是因为我的postgres数据库未配置为接受远程连接,并且已经使用this article中的指令编辑了postgres conf文件以允许远程连接。

尝试连接到在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地址,尽管IP地址已更改,但到目前为止,它始终在172.17.0.x范围内

有什么想法为什么我无法连接到该数据库?我想象的可能很简单!

我正在运行Ubuntu 14.04; Postgres 9.3

最佳方案

长话短说

  1. 使用172.17.0.0/16作为IP地址范围,而不是172.17.0.0/32

  2. 不要使用localhost连接到主机上的PostgreSQL数据库,而要使用主机的IP。为了使容器可移植,请使用--add-host=database:<host-ip>标志启动容器,并使用database作为连接到PostgreSQL的主机名。

  3. 确保PostreSQL配置为侦听所有IP地址上的连接,而不仅仅是localhost上的连接。在PostgreSQL的配置文件中查找设置listen_addresses,通常在/etc/postgresql/9.3/main/postgresql.conf中找到(贷方为@DazmoNorton)。

长版

172.17.0.0/32不是IP地址范围,而是单个地址(名称为172.17.0.0)。没有Docker容器将永远不会分配该地址,因为它是Docker桥(docker0)接口的网络地址。

Docker启动时,它将创建一个新的桥接网络接口,您可以在调用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,其网络掩码为/16(或255.255.0.0)。这意味着网络地址为172.17.0.0/16

IP地址是随机分配的,但是没有任何其他配置,它将始终位于172.17.0.0/16网络中。对于每个Docker容器,将从该范围分配一个随机地址。

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

次佳方案

Docker for Mac解决方案

17.06起

感谢@Birchlabs的评论,现在使用special Mac-only DNS name available可以轻松得多:

docker run -e DB_PORT=5432 -e DB_HOST=docker.for.mac.host.internal

从17.12.0-cd-mac46开始,应使用docker.for.mac.host.internal而不是docker.for.mac.localhost。有关详细信息,请参见release note

旧版

@helmbert的答案很好地解释了这个问题。但是适用于Mac的Docker does not expose the bridge network,所以我不得不做这个技巧来解决该限制:

$ 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而不是docker0网络接口的IP地址。

第三种方案

适用于mac的简单解决方案:

最新版本的docker(18.03)提供了内置的端口转发解决方案。在您的Docker容器内部,只需将数据库主机设置为host.docker.internal即可。这将转发到运行Docker容器的主机。

有关此文档,请参见:https://docs.docker.com/docker-for-mac/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host

第四种方案

简单的解决方案

只需将--network=host添加到docker run即可。就这样!

这样,容器将使用主机的网络,因此localhost127.0.0.1将指向主机(默认情况下,它们指向容器)。例:

docker run -d --network=host \
  -e "DB_DBNAME=your_db" \
  -e "DB_PORT=5432" \
  -e "DB_USER=your_db_user" \
  -e "DB_PASS=your_db_password" \
  -e "DB_HOST=127.0.0.1" \
  --name foobar foo/bar

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/10254.html,未经允许,请勿转载。