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

时间:2016-03-10 22:31:23

标签: postgresql docker

我试图使用Docker容器来运行PostgreSQL服务器,并从我的主机连接它。

我的配置是:

  • 主机:Mac OS X 10.10.5
  • Docker 1.10.1

我已经这样做了:

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

docker volume create --name postgres_data

第2步:启动postgres实例

UPDATE :正如评论中所建议的那样,我在运行容器时指定了端口映射

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)

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

它开始了! (而且它不应该)。我甚至可以使用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(),它会显示在我的docker实例中运行的postgres,同时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实例连接。我怎么能这样做?

6 个答案:

答案 0 :(得分:9)

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

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

答案 1 :(得分:7)

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

docker-machine ip

答案将是 192.168.99.100

使用-p 5432:5432交换机映射端口后,您可以使用所提到的IP地址通过dev机器上的任何工具连接到postgres。

答案 2 :(得分:1)

我有一个类似的问题。我的问题很简单,就是0.0.0.0没有映射到本地主机,所以我只需要添加到psql

psql --host=0.0.0.0

这是推测

docker port <container name>

输出

5432/tcp -> 0.0.0.0:5432

答案 3 :(得分:1)

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

要获取容器ID,请运行

docker ps

找到所需的容器ID并运行

docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <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

答案 4 :(得分:1)

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

#include <iostream>

using namespace std;

void reverse(int num) {
  int rem = 0;

  while (num != 0) {
    rem = rem * 10 + num % 10;
    num = num / 10;
  }

  cout << rem << endl;
}

int main() {
  int num;

  while (num != 0) {
    cin >> num;
    reverse(num);

    if (num == 0)
      break;
  }

  return 0;
}

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

答案 5 :(得分:0)

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

给出命令:

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,因此也可以使用。