从主机连接到运行在Docker容器中的PostgreSQL

24

我怎样才能从主机连接到运行在docker中的postgres?

docker-compose.yml

version: '2'

networks:
    database:
        driver: bridge
services:
    app:
        build:
            context: .
            dockerfile: Application.Dockerfile
        env_file:
            - docker/Application/env_files/main.env
        ports:
            - "8060:80"
        networks:
           - database
        depends_on:
            - appdb

    appdb:
        image: postdock/postgres:1.9-postgres-extended95-repmgr32
        environment:
            POSTGRES_PASSWORD: app_pass
            POSTGRES_USER: www-data
            POSTGRES_DB: app_db
            CLUSTER_NODE_NETWORK_NAME: appdb
            NODE_ID: 1
            NODE_NAME: node1
        ports:
            - "5432:5432"
        networks:
            database:
                aliases:
                    - database

docker-compose ps

:列出由docker-compose管理的所有容器,并显示它们的状态。
           Name                          Command               State               Ports
-----------------------------------------------------------------------------------------------------
appname_app_1     /bin/sh -c /app/start.sh         Up      0.0.0.0:8060->80/tcp
appname_appdb_1   docker-entrypoint.sh /usr/ ...   Up      22/tcp, 0.0.0.0:5432->5432/tcp

我可以成功地从容器连接,无论是从应用程序容器还是数据库容器。

在容器内运行 psql 可以列出数据库和用户的列表:

# psql -U postgres
psql (9.5.13)
Type "help" for help.

postgres=# \du
                                       List of roles
    Role name     |                         Attributes                         | Member of
------------------+------------------------------------------------------------+-----------
 postgres         | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 replication_user | Superuser, Create role, Create DB, Replication             | {}
 www-data         | Superuser                                                  | {}

postgres=# \l
                                       List of databases
      Name      |      Owner       | Encoding |  Collate   |   Ctype    |   Access privileges
----------------+------------------+----------+------------+------------+-----------------------
 app_db         | postgres         | UTF8     | en_US.utf8 | en_US.utf8 |
 postgres       | postgres         | UTF8     | en_US.utf8 | en_US.utf8 |
 replication_db | replication_user | UTF8     | en_US.utf8 | en_US.utf8 |
 template0      | postgres         | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
                |                  |          |            |            | postgres=CTc/postgres
 template1      | postgres         | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
                |                  |          |            |            | postgres=CTc/postgres
(5 rows)

DB镜像不是官方的postgres镜像。但是在GitHub上的Dockerfile看起来很好。

从DB容器中查看/var/lib/postgresql/data/pg_hba.conf:

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
#local   replication     postgres                                trust
#host    replication     postgres        127.0.0.1/32            trust
#host    replication     postgres        ::1/128                 trust

host all all all md5
host replication replication_user 0.0.0.0/0 md5

我尝试过两个用户,但没有运气。

$ psql -U postgres -h localhost
psql: FATAL:  role "postgres" does not exist
$ psql -h localhost -U www-data appdb -W
Password for user www-data:
psql: FATAL:  role "www-data" does not exist

看起来我的主机上已经有一个在该端口上运行的 PSQL 了。我该如何检查它?


你在尝试使用哪个操作系统? - Tarun Lalwani
我正在OSX上运行它。 - mef_
你如何检查主机上是否已经在同一端口运行了postgresql?为什么不停止容器并运行psql呢? - ikusimakusi
6个回答

19
我认为问题在于您的本地机器上有一个运行在端口5432的Postgres。 问题可以通过将Docker容器的端口5432映射到主机机器上的另一个端口来解决。 这可以通过docker-compose.yml文件进行更改实现。

更改:

"5432:5432" 
to
"5433:5432"

重启docker-compose

现在docker容器postgres运行在5433端口。(本地安装的postgres运行在5432端口) 你可以尝试连接到docker容器。

psql -p 5433 -d db_name -U user -h localhost

1
谢谢!我遇到了与原问题完全相同的问题。你的答案对我有用! - Philip
1
谢谢你,你激励了我。但是对于我的情况,为了使其工作,我必须指定psql的主机为0.0.0.0。就像这样:psql -p 5433 -h 0.0.0.0 -U postgres - worrawut
我可以确认通常只需更改两个端口号中的第一个就可以解决问题,因为由于本地安装使用的默认端口是5432,所以会出现端口冲突。两个端口中的第一个是用于Linux上Docker主机端口的。如果已经被占用,则无法使用该端口来访问主机。同样的技巧也适用于docker-compose,请参见从Windows Docker主机连接到dockerized postgres?和https://dev59.com/-1oU5IYBdhLWcg3wM1C9#55259785。 - questionto42

3

我在Ubuntu 16.04上运行了这个程序。

$ psql -h localhost -U www-data app_db
Password for user www-data:
psql (9.5.13)
Type "help" for help.

app_db=# \du
                                       List of roles
    Role name     |                         Attributes                         | Member of
------------------+------------------------------------------------------------+-----------
 postgres         | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 replication_user | Superuser, Create role, Create DB, Replication             | {}
 www-data         | Superuser                                                  | {}

以下是从我的 Mac 到运行 Docker 的虚拟机内部的 IP(192.168.33.100 是 Docker 虚拟机的 IP 地址)

$ psql -h 192.168.33.100 -U www-data app_db
Password for user www-data:
psql (9.6.9, server 9.5.13)
Type "help" for help.

app_db=# \du
                                       List of roles
    Role name     |                         Attributes                         | Member of
------------------+------------------------------------------------------------+-----------
 postgres         | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 replication_user | Superuser, Create role, Create DB, Replication             | {}
 www-data         | Superuser                                                  | {}

他们都为我工作。

虚拟机上的PSQL版本

$ psql --version
psql (PostgreSQL) 9.5.13

Mac上的PSQL版本

$ psql --version
psql (PostgreSQL) 9.6.9

Working


这对我不起作用。看起来我的主机上已经有一个在该端口上运行的PSQL了。我该如何检查它? - mef_
要检查已使用的端口,请使用以下命令之一:lsof -i -P -n | grep 5432ss -tulwn | grep 5432netstat -tulpn | grep 5432。建议在这些命令中使用 sudo,并且我相信最后两个命令在 Mac 上不可用。 - Esmaeil MIRZAEE

2

在使用官方的docker容器运行Postgres 10时,我在elementary OS 5.0上遇到了同样的问题。不过,我可以通过正在运行的容器的IP地址从主机连接到它。

sudo docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name/id

获取IP地址后进行测试: psql -h 172.17.0.2 -U postgres


一条评论提到他们正在使用OSX;在MacOS主机(以及其他地方),docker inspect IP地址是无法访问的,而且在任何平台上都不是必需的。 - David Maze

1
我相信你在pg_hba.conf中遇到了问题。在这里,你指定了一个可以访问的主机 - 127.0.0.1/32。
你可以将其更改为以下内容:
# IPv4 local connections:
host    all             all             0.0.0.0/0            md5

这将确保您的主机(完全不同的IP)可以连接。
要检查是否已经运行了postgresql的实例,可以执行netstat -plnt | grep 5432。如果从中获得任何结果,则可以获取PID并验证进程本身。

感谢 netstat | grep 5432 的提示。我用它找到了已经在本地运行的 postgres。 - Philip

0

我有一个相对类似的设置,以下内容适用于我在主机上打开psql会话进入docker postgres实例:

docker-compose run --rm db psql -h db -U postgres -d app_development

其中:

  • db是容器的名称
  • postgres是用户的名称
  • app_development是数据库的名称

所以对于你来说,它看起来像这样:docker-compose run --rm appdb psql -h appdb -U www-data -d app_db


我需要从主机访问权限。 - mef_
@mef_ 我更新了我的回答,更具体地说明了命令的作用。如果你尝试过了,有什么具体不起作用的地方吗? - antislice

0

由于您正在OSX上运行它,因此您可以始终使用预安装的网络实用程序应用程序在主机上运行端口扫描并确定postgres服务器是否正在运行(如果是,则在哪个端口上)

但我不认为您在主机上运行一个。问题在于Postgres默认运行在5432上,而您尝试运行的docker-compose文件将db容器暴露在相同的端口上,即5432。如果Postgres服务器已在主机上运行,则Docker将尝试将容器暴露到已经被使用的端口,从而导致错误。

另一个潜在的解决方案:
answer所示,mysql打开了与localhost而不是tcp套接字的unix套接字。这里可能发生了类似的事情。

尝试在连接到容器中的服务器时使用127.0.0.1而不是localhost


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