Postgres 9.1 的 Docker 容器未将端口 5432 暴露给主机

Posted

技术标签:

【中文标题】Postgres 9.1 的 Docker 容器未将端口 5432 暴露给主机【英文标题】:Docker container for Postgres 9.1 not exposing port 5432 to host 【发布时间】:2016-06-26 00:23:45 【问题描述】:

我正在尝试使用 Docker 容器来运行 PostgreSQL 服务器,并从我的主机与其连接。

我的配置是:

主机:Mac OS X 10.10.5 Docker 1.10.1

我已经这样做了:

第 1 步:为永久 postgres 数据创建一个卷

docker volume create --name postgres_data

第 2 步:启动 postgres 实例

更新:按照cmets的建议,我在运行容器时指定了端口映射

docker run --name my_postgres_container -e POSTGRES_PASSWORD=my_password -v postgres_data:/var/lib/postgresql/data -p 5432:5432 -d postgres:9.1

第 3 步:通过以下方式连接到 Docker 实例:

docker run -it --link my_postgres_container:postgres --rm postgres:9.1 sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'

但我想通过以下方式连接到该实例:

psql -h localhost -p 5432 -U postgres

就像我在我的主机上本地安装了 Postgres。

问题是5432端口没有暴露。所以,我无法连接它:

sudo lsof -i -P | grep -i "listen" --> 5432 端口未打开

更新 2:更陌生。我也这样做了:

停止 Docker。然后,在我的主机上运行一个普通的 PostgreSQL 9.4.4 实例(这里不涉及 docker,只是在我的 Mac OS X 主机上运行 postgres,侦听端口 5432)。一切正常:

sudo lsof -i -P | grep -i "postgres"

postgres  14100          jorge    6u  IPv4 0x780274158cebef01      0t0  TCP localhost:5432 (LISTEN)

我可以毫无问题地连接到我的本地 postgres 实例(查看命令的输出:是为我的主机 Mac OS X 编译的 postgres):

psql -h localhost -U postgres -c "select version()"
                                                                version
---------------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 9.4.4 on x86_64-apple-darwin14.3.0, compiled by Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn), 64-bit
(1 row)

现在是有趣的部分。我再次启动我的 Docker 实例,在主机 PostgreSQL 实例运行时。

开始了! (它不应该)。我什至可以使用 docker run 连接...

docker run -it --link my_postgres_instance:postgres --rm postgres:9.1 sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'

如果我现在运行 select version(),它显示 postgres 在我的 docker 实例中运行,同时 postgres 在我的主机中运行,在 docker 之外,使用相同的 5432 端口。 (看输出,是为 Debian 编译的 postgres,postgres:9.1 容器内的操作系统)

postgres=# select version();
                                            version
------------------------------------------------------------------------------------------------
 PostgreSQL 9.1.20 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
(1 row)

为什么?

这有意义吗?我的最终目标是在另一个 Docker 容器中运行 Django 应用程序并连接到我的 Postgres 实例。我怎么能那样做?

【问题讨论】:

【参考方案1】:

现在是 2018 年,我也遇到了类似的问题。对我来说,解决方案似乎是 docker 的道具顺序。例如这导致没有端口被暴露;

docker run -d --name posttest postgres:alpine -e POSTGRES_PASSWORD=fred -p 5432:5432

虽然这工作正常(图像暴露端口 5432 符合预期);

docker run --name posttest -d -p 5432:5432 -e POSTGRES_PASSWORD=fred postgres:alpine

【讨论】:

有人能解释一下为什么这个顺序很重要吗?谢谢 我的理解是,在镜像名称之后传递的args被定向到容器中运行的命令,而在镜像名称之前传递的args被传递给Docker 哇...它对我有用。万分感谢。我的mac上docs.docker.com/samples/library/postgres上的示例(查找2019may04)不起作用。我错过了什么吗?【参考方案2】:

您的 docker 主机是一个虚拟机,它有自己的 IP 地址。 您可以通过输入以下命令来检测此 IP 地址:

docker-machine ip

答案将类似于 192.168.99.100

当您使用 -p 5432:5432 开关映射端口后,您将能够使用提到的 IP 地址从您的开发机器上使用任何工具连接到 postgres。

【讨论】:

这是唯一对我有用的答案。看起来如果存在虚拟机,Docker 会将端口映射到这台机器而不是主机系统。【参考方案3】:

使用-p <host_port>:<container_port>:使用正确的端口映射运行 postgre 映像:

docker run --same-options-as-step-one -d -p 5432:5432 postgres:9.1

【讨论】:

谢谢!我已经做到了。但仍然无法使用 psql 连接。端口 5432 没有被暴露,或者我不知道如何连接。我主机的 psql 程序运行正常(我可以连接到其他主机,但不能连接到我的容器) docker port <container_name> 显示什么? 它应该打印类似5432/tcp -> 0.0.0.0:5432 5432/tcp -> 0.0.0.0:5432。尝试使用 -h 0.0.0.0 -p 5432。出现连接被拒绝错误:服务器是否正在运行...?我真的可以只使用普通的 psql 进行连接,还是需要运行另一个容器来测试 psql?因为官方文档没有使用正常的psql命令:hub.docker.com/_/postgres 你应该可以使用普通的psql..你试过-h 127.0.0.1 -p 5432吗?【参考方案4】:

我能够使用容器 IP 或主机 IP 进行连接,但 localhost (127.0.0.1) 除外。

获取容器 ID 运行

docker ps

找到所需的容器 id 并运行

docker inspect --format='range .NetworkSettings.Networks.IPAddressend' <container_id>

端口必须暴露。

这是一个 docker-compose.yml 的示例,它启动了两个容器 postgres 和 adminer,这是一个数据库管理工具,您可以使用它来连接到 postgres:

version: '3'
services:
  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080
  postgres:
    image: postgres:11.4-alpine
    restart: always
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres

【讨论】:

我得到了一个不同于 0.0.0.0 和 127.0.0.1 的 IP @mad_ 没关系,一定是容器IP。如果 postgres 端口被暴露,您应该能够使用该 IP 连接到它。【参考方案5】:

我遇到了类似的问题。我的问题只是 0.0.0.0 没有映射到 localhost 所以我只需要添加到 psql

psql --host=0.0.0.0

这是假设

docker port <container name>

输出

5432/tcp -> 0.0.0.0:5432

【讨论】:

【参考方案6】:

我在使用 Lubuntu 的 VMWare 虚拟机中工作时遇到了类似的问题。 VM 已暂停,然后重新启动。 PostgreSQL Docker 容器已正确映射并在 localhost:5432 上侦听,但我总是得到:

psql: server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.

重启虚拟机解决了我的问题。

【讨论】:

【参考方案7】:

其他答案有效,但不要解释它们为什么有效。

给定命令:

psql -h localhost -p 5432:5432 -U postgres

localhost 实际上是一个特殊值,它告诉 psql 寻找 unix 套接字连接,而不是通过 TCP。我们不能使用 unix 套接字连接到 docker 服务。

像这样更改命令,通过强制 TCP 来修复它:

psql -h 127.0.0.1 -p 5432:5432 -U postgres

只要您docker run ... -p 5432:5432 ...,它就会起作用。指定docker-machine ip 返回的 IP 也会强制使用 TCP,因此也可以。

【讨论】:

【参考方案8】:

试试这个来安装postgresql

 docker run --name postgres -d -p 5432:5432 -e POSTGRES_PASSWORD=fred postgres:alpine

或更改端口主机 Heree (mac)

 docker run --name postgres -d -p 5436:5432 -e POSTGRES_PASSWORD=fred postgres:alpine

提示: 安装 pgadmin4

docker run -p 5050:80  -e "PGADMIN_DEFAULT_EMAIL=name@example.com" -e "PGADMIN_DEFAULT_PASSWORD=admin"  -d dpage/pgadmin4

【讨论】:

以上是关于Postgres 9.1 的 Docker 容器未将端口 5432 暴露给主机的主要内容,如果未能解决你的问题,请参考以下文章

centos7下安装docker(9.1容器对资源的使用限制-CPU)

如何将节点 docker 容器与 postgres docker 容器连接起来

Docker - 如何在postgres容器中运行psql命令?

docker-compose:nodejs容器不与postgres容器通信

Docker 的 postgres 容器的密码验证失败

无法从 docker-compose 启动 postgres docker 容器