Docker - Postgres 和 pgAdmin 4:连接被拒绝

35

作为一个Docker新手,我正试图通过本地主机连接我的pgAdmin容器到Postgres容器。

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
0b00555238ba        dpage/pgadmin4      "/entrypoint.sh"         43 minutes ago      Up 43 minutes       0.0.0.0:80->80/tcp, 443/tcp   pedantic_turing
e79fb6440a95        postgres            "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:5432->5432/tcp        pg-docker

我成功使用psql命令连接。

psql -h localhost -U postgres -d postgres

但是当我在pgAdmin上使用与psql相同的参数创建服务器时,会出现以下错误。

无法连接到服务器:

无法连接到服务器:连接被拒绝。服务器是否运行在主机“localhost”(127.0.0.1)上,并接受端口5432上的TCP/IP连接? 无法连接到服务器:地址不可用。服务器是否运行在主机“localhost”(::1)上,并接受端口5432上的TCP/IP连接?

我成功地通过容器给出的IPAddress连接上了数据库。docker inspect

顺便说一下,我检查过postgresql.conf并确认了listen_addresses = '*' 并且pg_hba.conf包含 host all all all md5

但是我不明白,为什么我不能使用本地主机地址?为什么docker会给我一个不是本地的地址呢?


1
可能是什么是Docker容器内的localhost?的重复问题。 - David Maze
我在这里回答了:https://dev59.com/B18e5IYBdhLWcg3wo7mE#57729412 - Afshin Ghazi
8个回答

67
在这种情况下:
  1. Pgadmin无法连接到本地主机,但psql可以从docker外部工作。
  2. pgadmin和Postgres都作为容器运行。
虽然您没有明确说明是否这样做,但理想情况下,两个容器都可以成为自定义桥接网络的一部分,以实现自动DNS解析。
如果没有显式添加,它们将成为默认桥接网络的一部分。
要查找在docker运行时创建的网络,请输入: $ docker network ls 一些网络将在控制台中列出,也许您会找到一个[name]_default,这应该是您的网络。
执行 docker network inspect [name]_default 它会显示一堆信息,对我们来说最重要的是IPv4Address,类似于: "7c3cd7532ab8aacc70830afb74adad7296d9c8ddd725c498af2d7ee2d2c2aadd": {                 "Name": "intime_postegres_1",                 "EndpointID": "56a9cb574469f22259497b72719f9f4a3e555b09f95058fcf389ef5287381f28",                 "MacAddress": "02:42:ac:12:00:02",                 "IPv4Address": "172.18.0.2/16",                 "IPv6Address": ""             } 在pgAdmin的新服务器对话框中,不要使用localhost作为服务器名称/IP,而是连接到postgres实例的“IPv4Address”。
在我的情况下,连接到172.18.0.2:5432就像魔法一样工作。

1
谢谢,它可以工作,但并不是百分之百可靠的,因为重新启动会更改IP地址。 - hakish
是的,我还没有想出来,但也许有一个好的解决方案。我只在开发环境中使用过。你有什么线索吗? - Alex
3
使用 name 而非 IP 地址进行访问,在重启后仍能正常工作。 - Waweru Kamau
该解决方案仅适用于本地或同一域/内网。它不适用于公共IP地址。 - Jagesh Maharjan

31

我也遇到过这种情况,可以在终端上使用psql命令连接,但无法在pgAdmin4上连接。以下解决方法对我有效。

首先 -

docker ps

从那里,您将获得Postgres容器的容器名称/ID,然后执行 -

docker inspect name_of_container_here

它将给你类似于这样的东西 -

 "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "f35dbe66b36cd38673aad6e1278ad33031ef9d5abd34582d4b91955e288f855e",
                    "EndpointID": "2e63ea59e9d0de7526bb02ba29bc0b16bcad51b8963127ad380416d15da994db",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
注意IPAddress,并在pgAdmin4中创建新服务器时提供它 - enter image description here

1
创建新的服务器以便Docker访问Postgres真的帮了我很多,谢谢! - Tiara
相同的,172.17.0.2 对我也起作用。但是令人困扰的是本地主机名无法使用...为什么会这样呢?在 Docker 中启动 pgadmin,然后在浏览器中输入本地主机名就可以打开 pgadmin... - Victorio Berra

14

我遇到了同样的问题,但是我用了一种非规范的方法来解决它,这对我的本地工作流非常满意。

我总是使用一个docker-compose.yaml文件启动我的postgresql容器。所以我只需将pgAdmin添加到同一个compose文件中:

version: "3.7"
services:
  my_awesome_db:
    image: postgres:latest
    ports:
      - "5432:5432"
    container_name: postgresql-local
    volumes:
      - "/var/run/postgres.sock:/var/run/postgres/postgres.sock"
      - "/home/myuser/docker-apps/volumes/postgres-data:/var/lib/postgresql/data"
  pg_admin:
    image: dpage/pgadmin4:latest
    container_name: pgadmin4
    ports:
      - "15432:80"
    environment:
      - GUNICORN_THREADS=1
      - PGADMIN_DEFAULT_EMAIL=my_awesome_email@email.com
      - PGADMIN_DEFAULT_PASSWORD=does_not_matter
    depends_on:
      - my_awesome_db

所以我通过localhost:15432访问pgAdmin(只是因为它容易记住),并且我已经配置好了pgAdmin:

Host: my_awesome_db
Port: 5432
Username: postgres

我认为“localhost:5050”很容易记住,但除此之外,你的解决方案对我很有效。顺便说一下,我正在使用Docker for Windows。谢谢! - Ekown
2
这里的关键点是在通过pgAdmin连接时,使用容器服务名称(my_awesome_dbpg_admin)作为主机名。来自官方文档Compose中的网络默认情况下,Compose为您的应用程序设置单个网络。每个服务的容器都加入了默认网络,并且可以被该网络上的其他容器访问,并且可以通过与容器名称相同的主机名被发现。 - BeshEater

7

4
首先,您需要获取容器信息。
$docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
0b00555238ba        dpage/pgadmin4      "/entrypoint.sh"         43 minutes ago      Up 43 minutes       0.0.0.0:80->80/tcp, 443/tcp   pedantic_turing
e79fb6440a95        postgres            "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:5432->5432/tcp        pg-docker

然后提取IP地址。
$sudo docker inspect e79fb6440a95 | grep IPAddress

            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "192.168.64.2",


当你创建服务器时,请输入你的IP地址。

enter image description here


1
docker inspect 命令返回的 IP 地址是不稳定的;如果容器被删除或重新创建,该地址可能会更改。您永远不需要查找它。 - David Maze

1

您只需要在连接字符串中指定服务器参数和容器名称,而不是使用localhost或127.0.0.1。


请问您能分享一下屏幕截图或者代码片段吗? - Victorio Berra

0
我的pgAdmin运行在docker主机上(osx)。在docker-compose.yml中,我不得不设置
ports:
  - 5432:5432

明确的。这一行以前没有。但是这个一行的代码解决了问题。
这是我的示例:
version: '3.9'

services:

  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_PASSWORD: mysecret
      POSTGRES_USER: myuser
      POSTGRES_DB: mydb
    ports:
      - 5432:5432
    ...
    ...

在那之后,我可以使用pgadmin连接到“localhost”。而且,如果您重新启动容器,它是安全的!您无需使用docker inspect搜索ip地址。
如果您不这样做,您的docker将没有一个HostIp“0.0.0.0”,而只有一个tcp 5432连接。
背景信息:
1. 检查正在运行的docker容器docker ps 2. 获取您的pgsql的名称并执行docker inspect name_of_container_here 3. 找到“Ports”行
在更改docker-compose.yml之前,docker-inspect ...将显示“Ports”5432/tcp为null:
...
"Ports": {
    "5432/tcp": null
},
...

更改docker-compose.yml后,docker inspect ...将显示以下内容,您现在可以看到"HostIp": "0.0.0.0"等等...
...
"Ports": {
    "5432/tcp": [
        {
           "HostIp": "0.0.0.0",
           "HostPort": "5432"
        }
    ]
},
...

-1
因为我正在连接主机上的服务器,所以只需在docker run命令中添加
--net host
即可让容器访问主机的端口。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接