我曾经使用脚本(/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
执行时为何起作用?
答案 0 :(得分:2)
this commit似乎破坏了您的脚本。
说明:
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
时,您会看到在执行所有初始化脚本时,PostgreSQL依次stopped和started进入正常(运行)模式,即它同时在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
。