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

mar*_*y_c 105 ubuntu qgis docker postgresql-9.3

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

一切都很好,虽然我无法连接到包含我所有GIS数据的localhost postgres数据库.我认为这是因为我的postgres数据库没有配置为接受远程连接,并且已经使用本文中的说明编辑了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容器docker ps的IP地址,虽然IP地址发生了变化,但到目前为止一直在172.17.0.x范围内.

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

我正在运行Ubuntu 14.04; Postgres 9.3

hel*_*ert 120

TL; DR

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

长版

172.17.0.0/32不是一系列 IP地址,而是一个地址(namly 172.17.0.0).没有Docker容器会分配该地址,因为它是Docker bridge(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
Run Code Online (Sandbox Code Playgroud)

如您所见,在我的例子中,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.

  • 我还需要一件.我还必须编辑`/ etc/postgresql/9.3/main/postgresql.conf`并将我的服务器的`eth0` IP地址添加到`listen_addresses`.默认情况下,`listen_addresses`只有postgres绑定到`localhost`. (6认同)

bax*_*ang 49

Docker for Mac解决方案

17.06起

感谢@Birchlabs的评论,现在使用这个特殊的Mac专用DNS名称可以轻松实现:

docker run -e DB_PORT=5432 -e DB_HOST=docker.for.mac.host.internal
Run Code Online (Sandbox Code Playgroud)

从17.12.0-cd-mac46,docker.for.mac.host.internal应该用来代替docker.for.mac.localhost.有关详情,请参阅发行说明

旧版本

@ helmbert的答案很好地解释了这个问题.但是Docker for Mac 并没有公开桥接网络,所以我不得不这样做来解决这个限制:

$ sudo ifconfig lo0 alias 10.200.10.1/24
Run Code Online (Sandbox Code Playgroud)

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

host    all             all             10.200.10.1/24            trust
Run Code Online (Sandbox Code Playgroud)

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

listen_addresses = '*'
Run Code Online (Sandbox Code Playgroud)

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

$ PGDATA=/usr/local/var/postgres pg_ctl reload
$ docker run -e DB_PORT=5432 -e DB_HOST=10.200.10.1 my_app 
Run Code Online (Sandbox Code Playgroud)

这个解决方法的作用基本上与@helmbert的答案相同,但是使用附加到的IP地址lo0而不是docker0网络接口.

  • 从Docker 17.06.0-rc1-ce-mac13(2017年6月1日)开始,macOS上有更好的方法.容器识别主机`docker.for.mac.localhost`.这是主机的IP.在容器的主机数据库中查找它的条目如下:`docker run alpine/bin/sh -c'getent hosts docker.for.mac.localhost'` (6认同)
  • 似乎从18.03开始它变为`host.docker.internal`,其他选项仍然可用但不推荐使用([来源](https://docs.docker.com/docker-for-mac/release-notes/#docker-社区版-18030-CE-mac59-2018-03-26)). (4认同)
  • 截至2017年4月4日,这仍然是最新的吗? (3认同)

Max*_*ysh 31

简单的解决方案

只需添加--network=hostdocker run. 就这样!

这样容器将使用主机的网络,因此localhost并且127.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
Run Code Online (Sandbox Code Playgroud)

  • 当心!这个解决方案,在我看来是正确的,不适用于 macOS。不要浪费你的时间试图找出它为什么不起作用。看看:https://github.com/docker/for-mac/issues/2716 (7认同)
  • 适用于 Debian。尝试更改 postgresql.conf 和 pg_hba.conf 但这更简单、更快。 (2认同)

Chr*_*ris 27

mac的简单解决方案:

最新版本的docker(18.03)提供内置端口转发解决方案.在docker容器中,只需将db主机设置为host.docker.internal.这将被转发给运行docker容器的主机.

有关此文档,请访问:https://docs.docker.com/docker-for-mac/networking/#per-container-ip-addressing-is-not-possible

  • 这是迄今为止最好的答案!方式更容易以及它应该如何。 (5认同)
  • 仅适用于 Windows 和 Mac。就我而言,ubuntu 无法正常工作 (5认同)
  • 文档说“这是出于开发目的,不适用于 Docker Desktop 之外的生产环境。”。我还将在生产设置中连接到远程数据库。这种情况我该怎么办? (4认同)
  • `host.docker.internal` 仅限于 macs 吗? (2认同)

Shu*_*ham 15

--network=host您可以在命令期间传递docker run来访问localhost容器内部。

前任:

docker run --network=host docker-image-name:latest
Run Code Online (Sandbox Code Playgroud)

如果您想通过 localhost 传递环境变量,请使用--env-file参数来访问容器内的环境变量。

前任:

docker run --network=host --env-file .env-file-name docker-image-name:latest
Run Code Online (Sandbox Code Playgroud)

注意:在docker镜像名称之前传递参数,否则参数将不起作用。(我遇到过这个,所以请注意!)

  • 你将如何在 docker-compose 中编写这个? (4认同)
  • 请注意,此选项会放弃端口映射。在主机网络模式下,容器共享主机的网络命名空间。即,如果容器中的应用程序在 :80 上运行,则它将在主机上的 :80 上可用。https://docs.docker.com/network/host/ (2认同)

sin*_*eep 13

此处发布的解决方案对我不起作用。因此,我发布此答案以帮助面临类似问题的人。

注意:此解决方案也适用于 Windows 10,请查看下面的评论。

操作系统:Ubuntu 18
PostgreSQL:9.5(在 Ubuntu 上托管)
Docker:服务器应用程序(连接到 PostgreSQL)

我正在使用 docker-compose.yml 来构建应用程序。

第 1 步:请添加host.docker.internal:<docker0 IP>

version: '3'
services:
  bank-server:
    ...
    depends_on:
      ....
    restart: on-failure
    ports:
      - 9090:9090
    extra_hosts:
      - "host.docker.internal:172.17.0.1"
Run Code Online (Sandbox Code Playgroud)

要查找 docker 的 IP,i.e. 172.17.0.1 (in my case)您可以使用:

$> ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
Run Code Online (Sandbox Code Playgroud)

或者

$> ip a
1: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
Run Code Online (Sandbox Code Playgroud)

第 2在 postgresql.conf 中,将 listen_addresses 更改为listen_addresses = '*'

第 3在 pg_hba.conf 中,添加这一行

host    all             all             0.0.0.0/0               md5
Run Code Online (Sandbox Code Playgroud)

第 4现在使用重新启动 postgresql 服务,sudo service postgresql restart

步骤 5:请使用host.docker.internal主机名从服务器应用程序连接数据库。
前任:jdbc:postgresql://host.docker.internal:5432/bankDB

享受!!

  • `sudo nano /etc/postgresql/&lt;your_version&gt;/main/postgresql.conf` 对于那些想要编辑 postgres conf 的人 (2认同)
  • 谢谢,步骤2和3解决了我的问题。就我而言,我将新的“pg_hba”条目的“method”设置为“password”。另外,您不必开放对所有 IP (`0.0.0.0/0`) 的访问,而是可以使用 docker 桥接 IP (使用 `ip -h -ca` 来查找该 IP),在我的例子中是“172.17.0.1/16” (2认同)

Har*_*lin 6

为了设置一些简单的东西来允许 Postgresqldocker 容器连接到我的本地主机,我在 postgresql.conf 中使用了它:

listen_addresses = '*'
Run Code Online (Sandbox Code Playgroud)

并添加了这个pg_hba.conf:

host    all             all             172.17.0.0/16           password
Run Code Online (Sandbox Code Playgroud)

然后重新启动。然后,来自docker 容器(位于 172.17.0.2)的客户端可以使用主机:密码、数据库、用户名和密码连接到在我的本地主机上运行的 Postgresql。


Igr*_* Pn 6

让我尝试解释一下我做了什么。

\n

PostgreSQL

\n

首先,我进行了所需的配置,以确保我的 Postgres 数据库接受来自外部的连接。

\n

打开pg_hba.conf并在最后添加以下行:

\n
host    all             all             0.0.0.0/0               md5\n
Run Code Online (Sandbox Code Playgroud)\n

打开postgresql.conf并查找listen_addresses并修改,如下所示:

\n
listen_addresses = \'*\'\n
Run Code Online (Sandbox Code Playgroud)\n

确保上面的行没有注释#

\n

-> 重新启动数据库

\n

OBS:这不是生产环境的推荐配置

\n

接下来,我寻找我的 host\xe2\x80\x99s ip。我使用的是本地主机ip127.0.0.1,但容器看不到它,因此在运行容器时会显示相关的 Connection Refused 消息。在网上对此进行了长时间的搜索后,我读到容器看到了来自本地网络的内部IP(您的路由器将其归因于连接到它的每个设备,i \ xe2 \ x80 \ x99m而不是谈论给出的IP)您可以访问互联网)。也就是说,我打开了一个终端并执行了以下操作:

\n

查找本地网络ip

\n

打开终端或 CMD

\n

(MacOS/Linux)

\n
$ ifconfig\n
Run Code Online (Sandbox Code Playgroud)\n

(视窗)

\n
$ ipconfig\n
Run Code Online (Sandbox Code Playgroud)\n

此命令将显示您的网络配置信息。\n看起来像这样:

\n
en4: \n    ether d0:37:45:da:1b:6e \n    inet6 fe80::188d:ddbe:9796:8411%en4 prefixlen 64 secured scopeid 0x7 \n    inet 192.168.0.103 netmask 0xffffff00 broadcast 192.168.0.255\n    nd6 options=201<PERFORMNUD,DAD>\n    media: autoselect (100baseTX <full-duplex>)\n    status: active\n
Run Code Online (Sandbox Code Playgroud)\n

寻找活跃的那个。

\n

就我而言,我的本地网络 IP 是192.168.0.103

\n

完成此操作后,我运行了容器。

\n

码头工人

\n

使用以下命令运行容器--add-host,如下所示:

\n
$ docker run --add-host=aNameForYourDataBaseHost:yourLocalNetWorkIp --name containerName -di -p HostsportToBind:containerPort imageNameOrId\n
Run Code Online (Sandbox Code Playgroud)\n

就我而言,我做了:

\n
$ docker run --add-host=db:192.168.0.103 --name myCon -di -p 8000:8000 myImage\n
Run Code Online (Sandbox Code Playgroud)\n

我\xe2\x80\x99m 使用Django,所以8000端口是默认的。

\n

Django应用程序

\n

访问数据库的配置是:

\n

settings.py

\n
DATABASES = {\n    \'default\': {\n            \'ENGINE\': \'django.db.backends.postgresql\',\n            \'NAME\': \xe2\x80\x98myDataBaseName\',\n            \'USER\': \xe2\x80\x98username\',\n            \'PASSWORD\': \'123456\',\n            \'HOST\': \'192.168.0.103\',\n            \'PORT\': 5432,\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

参考

\n

关于-p标志:\n使用网络端口映射进行连接

\n

关于docker run:\n Docker 运行文档

\n

有趣的文章:\n Docker 技巧 #35:连接到在 Docker 主机上运行的数据库

\n


Sar*_* Ak 5

对于 docker-compose,您可以尝试添加

network_mode: "host"
Run Code Online (Sandbox Code Playgroud)

例子 :

version: '2'
services:
  feedx:
    build: web
    ports:
    - "127.0.0.1:8000:8000"
    network_mode: "host"
Run Code Online (Sandbox Code Playgroud)

https://docs.docker.com/compose/compose-file/#network_mode

  • 将networkd_mode添加到主机会中断另一个容器之间的连接 (5认同)

小智 5

3步解决方案

1.更新docker-compose文件

首先,由于数据库是本地的,我们需要通过在容器服务中添加以下配置来将主机网络绑定到容器

services:
    ...
    my-web-app:
        ...
        extra_hosts:
          -  "host.docker.internal:host-gateway"
        ...
    ...
Run Code Online (Sandbox Code Playgroud)

2.更新/etc/postgresql/12/main/pg_hba.conf

如果此目录下不存在该文件,请使用find / -name 'pg_hba.conf'查找它。

在评论标签下添加以下行# IPv4 local connections:

host    all             all             172.17.0.1/16           md5
Run Code Online (Sandbox Code Playgroud)

3. 更新/etc/postgresql/12/main/postgresql.conf

如果此目录下不存在该文件,请使用find / -name 'postgresql.conf'查找它。

找到以下行(该行可能被注释)

#listen_addresses = 'localhost'
Run Code Online (Sandbox Code Playgroud)

并将其更改为以下行以便能够从本地主机连接到 postgres 并172.17.0.1

listen_addresses = 'localhost,172.17.0.1'
Run Code Online (Sandbox Code Playgroud)

您也可以将其更改为以下内容,但不建议在生产中这样做,因为它会将数据库暴露给全世界(意味着任何IP地址都可以连接到数据库)

listen_addresses = '*'
Run Code Online (Sandbox Code Playgroud)

最后不要忘记:

  1. 使用以下命令重新启动 postgres 服务sudo systemctl restart postgresql
  2. 将连接字符串主机更新为host.docker.internal