在/docker-entrypoint-initdb.d/db_init.sh中运行psql命令时出错(psql:无法连接到服务器:连接被拒绝)

时间:2018-08-02 18:19:26

标签: postgresql docker docker-compose

我曾经使用脚本(/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执行时为何起作用?

1 个答案:

答案 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依次stoppedstarted进入正常(运行)模式,即它同时在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