如何进入正在运行的Postgres容器的psql?

71

我按照 fig 网站上的教程创建了一个 postgres 容器。我将容器命名为 db

容器正在运行,我的应用程序能够正常连接到它。当我尝试在运行db容器时运行命令 fig run db psql 时,出现了错误:

psql: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

如何在正在运行的db容器中进入psql接口?

5个回答

129

fig将创建一个使用不同名称的docker容器,而不是在fig.yml文件中使用的名称。

我通过查找docker ps并查看NAMES列来找到容器名称,然后在运行中的容器中使用docker exec -ti NAME_OF_CONTAINER psql -U YOUR_POSTGRES_USERNAME命令运行psql命令。

重要提示:

  • docker exec在正在运行的容器上运行psql命令
  • docker run将启动一个新容器。

更新

fig现已更名为docker-compose


3
好答案!区分 docker run <image>docker exec <container> 非常重要。你也可以只使用 docker exec -it <container> /bin/bash 进行开发 - schmunk
需要转储数据,无法使用docker exec -it命令。 - rocketspacer
3
可能还需要像这样提到数据库名称:docker exec -ti NAME_OF_CONTAINER psql -U YOUR_POSTGRES_USERNAME DATABASE - Fazle Rabbi
这个解决方案可能有效,但它回答了回答正文中提出的更具体的问题,而问题标题则关注更一般的问题。我认为更一般的答案对于Stackoverflow更有价值。 - TZubiri

24

与其连接:

psql

使用 -h 和 -p 选项:

psql -h localhost -p 5432

为什么这样做可行?

如果我们在本地运行psql而没有参数(或使用不正确的参数),psql将尝试通过unix套接字而不是tcp进行连接,因为这样更为高效。

然而,由于我们容器的文件系统是分离的设计,因此psql的微小优化不适用于我们古怪的设置。即使它不是这样,psql也不知道在哪里查找套接字文件。

解决方案不是编写庞大的docker exec命令,也不是挂载卷以便我们的本地psql实例可以在容器中找到套接字,而是将整个交互移至TCP。

当然,这可能略微低效,但我们使用容器的原因就是让事情即使在不同计算机中设置也能正常工作,TCP是docker容器之间通信的协议,无论是在同一台机器上还是不同机器上。

要告诉psql我们想要通过TCP连接,我们使用-h选项来标识(虚拟)机器,以及-p来标识postgresql进程,5432是默认端口。

psql -h localhost -p 5432

当没有给出任何参数时,psql可以尝试使用这些默认参数,但它选择尽早失败,并发出错误消息,让管理员自己解决连接细节问题。有关此决定的更多信息,请参见https://www.postgresql.org/message-id/20191217141456.GA2413%40elch.exwg.net


意味着本地机器上安装了psql客户端,但在我看来,这是一个干净而逻辑清晰的解决方案。 - outforawhile

19

我个人更喜欢将中间件部署为容器,而不是在主机系统上安装和维护它们:

docker run --rm --name postgresql -p 5432:5432
-e POSTGRES_USER=admin -e POSTGRES_PASSWORD=admin
-e POSTGRES_DB=demodb
-d postgres:latest
docker exec -it postgresql psql -d demodb -U admin

1
它对我有效。 docker exec -it <docker_container_name> /bin/bashpsql -d <postgres_db_name> -U <postgres_password> - claudius
如果容器没有psql客户端怎么办?这是一个明智的决定。 - TZubiri
1
我实际上正在使用第三方客户端(不想透露名称,但是是DBeaver)。 - Thomas Escolan

3
您需要运行一个新的容器来连接由fig启动的容器。这是因为默认情况下,主容器会启动服务,如果您运行fig run db psql,fig将不会启动服务,而是运行psql客户端。请参见Dockerfile
因此,要连接到PostgreSQL服务,您需要运行与由fig启动的容器链接的另一个容器。请参见https://registry.hub.docker.com/_/postgres/
首先,由于fig更改了启动的容器的名称,请在运行fig up后检查docker ps容器的NAMES列。然后:
docker run -it --link <postgres_container_name>:postgres --rm postgres sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'

您也可以像@sargas描述的那样使用 docker exec 技巧,但链接方式对我来说更加经典。


1
--link 标志是 Docker 的一个已弃用的遗留功能:https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/ - Ivan Rave

2

你能发布docker ps的结果吗?我猜测你需要指定postgres容器正在暴露的端口。运行docker ps应该会给你结果。

CONTAINER ID        IMAGE                          COMMAND                CREATED             STATUS              PORTS                    NAMES
948b1f6ebc0a        my_postgres:latest            "/usr/lib/postgresql   6 days ago          Up 6 days           0.0.0.0:49155->5432/tcp   db

在PORTS列下查找您的数据库容器,您将看到数据库实际上公开的端口。 在这种情况下,它是49155,但如果在容器启动时未明确指定,则Docker将在49153和65535之间选择随机端口。 您需要提供-p选项以便于psql定位该端口。
psql -p 49155 ... 

来源:https://docs.docker.com/userguide/dockerlinks/


2
对我来说,我需要运行 psql -h localhost -p 54322 -u postgres postgres - Nam G VU

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