postgresql - 在 /docker-entrypoint-initdb.d/db_init.sh 中运行 psql 命令时出错(psql:无法连接到服务器:连接被拒绝)
问题描述
我曾经使用脚本 ( /docker-entrypoint-initdb.d/db_init.sh
) 循环遍历复制到 postgres 容器中的文件夹中的数据库转储并恢复它们。它曾经工作得很好,但最近它停止了工作。
我收到以下错误:
postgres_server_1 | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/db_init.sh
postgres_server_1 | --> db_init.sh: Found /dumps/dataset_1.dump as dataset_1
postgres_server_1 | psql: could not connect to server: Connection refused
postgres_server_1 | Is the server running on host "localhost" (127.0.0.1) and accepting
postgres_server_1 | TCP/IP connections on port 5432?
该db_init.sh
脚本遍历包含数据库转储的文件夹并检查数据库是否已经存在。如果不是,它将恢复转储。
/docker-entrypoint-initdb.d/db_init.sh
内容:
shopt -s nullglob
for i in /dumps/*.dump;
do
db_name=${i##*/}
db_name=${db_name%.dump}
echo "--> db_init.sh: Found $i as $db_name"
if psql -U postgres -h localhost -lqt | cut -d \| -f 1 | grep -qw ${db_name}; then
echo "--> db_init.sh: Database ${db_name} already exists."
else
echo "--> db_init.sh: Setting up database: ${db_name}"
createdb -U postgres -h localhost-T template0 ${db_name}
psql -U postgres -h localhost ${db_name} < ${i}
fi
done
echo "--> db_init.sh: Setup complete."
我正在使用 docker-compose 来启动 postgres 容器(以及其他一些容器)。
内容docker-compose.yml
:
version: '3'
services:
postgres_server:
image: postgres
volumes:
- /etc/localtime:/etc/localtime:ro
- ./data/dumps:/dumps:ro
- ./scripts/db_init.sh:/docker-entrypoint-initdb.d/db_init.sh
environment:
- TZ=Europe/Berlin
restart: always
volumes:
postgres_data:
driver: local
现在我不明白的是,为什么似乎通常与尝试从不同的机器或容器连接到 postgres 数据库相关联的连接错误。但是脚本本身在 postgres 容器中运行,并且一个卷将包含转储的目录连接到容器中。psql
使用从容器内运行命令docker exec -it container_name bash
可以正常工作,并且转储在那里。为什么psql
命令在容器内手动执行时有效,但在通过执行时无效/docker-entrypoint-initdb.d/db_init.sh
?
解决方案
看起来这个提交破坏了你的脚本。
解释:
PostgreSQL 不仅可以通过 TCP/IP 接受连接,还可以通过 UNIX 套接字接受连接。该-h localhost
参数告诉psql
使用 TCP 连接而不是 UNIX 套接字。
如果您查看当前的docker-entrypoint.sh版本,您会看到,在/docker-entrypoint-initdb.d
PostgreSQL 中执行脚本期间,仅侦听 UNIX 套接字,并且启动日志显示:
LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
这意味着psql -h localhost
不会连接到数据库,因为 PostgreSQL 不侦听 IP 套接字。您必须使用psql
无 -h localhost
选项以使其使用 UNIX 套接字而不是 TCP 连接。
但为什么psql -h localhost
手动运行有效?
如果你docker-entrypoint.sh
再看一遍,你会看到当所有的 init 脚本被执行时,PostgreSQL 正在停止,然后在正常(操作)模式下再次启动,在这种模式下,它在 UNIX 和 IP 套接字上进行侦听:
LOG: listening on IPv4 address "0.0.0.0", port 5432
LOG: listening on IPv6 address "::", port 5432
LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
因此,当启动过程完成后,您可以使用 TCP 连接连接到 PostgreSQL,从而进入容器并运行psql -h localhost
成功。
推荐阅读
- git - 如何从已删除的 Git 存储库中恢复代码(文件)
- reactjs - 如何在管道中包含多个代码覆盖率
- javascript - 在 React 中访问 axios 范围之外的响应数据的方法
- html - 在 Django 中上传文件时表单无效
- rally - 是否可以使用 rally sdk 使用 highcharts 热图图表?
- c# - .net core 2.2,从用户机密中读取 serilog 的设置
- ios - 在 Firebase 身份验证中更新电话号码 - Swift
- laravel - 自定义方法不适用于 HasMany 关系
- asp.net - 将 OData 过滤器查询转换为 .NET 中的 Elasticsearch 查询?
- python - 第二个视频源 /dev/video1 在 python ubuntu 中不起作用