当docker容器启动时,如何通过psql(-h localhost -p 5432)连接到postgres

时间:2018-05-30 20:40:31

标签: postgresql docker docker-compose

我有一些docker-compose.yml文件。在此文件中定义了db service(postgres:9.6):

db:
image: postgres:9.6
volumes:
  - ./test/data/postgresql/:/var/lib/postgresql/data:delegated
  - ./test/bootstrap/postgres:/docker-entrypoint-initdb.d:delegated
ports:
  - 15432:5432
environment:
  - POSTGRES_DB=test
  - POSTGRES_USER=test
  - PGDATA=/var/lib/postgresql/data/testdata

一些sh脚本位于 ./test / bootstrap / postgres 中。在这个脚本中,我尝试通过psql连接到postgres,如:psql -U" $ POSTGRES_USER" -d" $ POSTGRES_DB" -h localhost -p 5432(我知道 -h localhost -p 5432 不是必需的,但我需要它。)
当我的容器出现错误时发生错误:

psql: could not connect to server: Connection refused 
   Is the server running on host "localhost" (127.0.0.1) and accepting 
   TCP/IP connections on port 5432? 

但在此之后我重新启动(首次启动此脚本后未执行)我的数据库容器然后在容器内部手动运行sh脚本并成功执行。它可以连接到localhost和端口5432,即使它是第一次启动。

如果我在脚本中连接psql -U" $ POSTGRES_USER" -d" $ POSTGRES_DB"没有连接错误。

有人能解释我这种奇怪的行为吗?为什么我无法连接到localhost:5432当容器启动但是如果从容器手动连接它连接成功?

谢谢!

3 个答案:

答案 0 :(得分:1)

我的理解是,在容器初始化期间,服务器正在侦听Unix域套接字。

LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"

当服务器以此模式运行时,将执行docker-entrypoint-init.d目录中的脚本。您正尝试通过指定-h localhost来通过TCP / IP进行连接。 尝试删除该参数以使用Unix套接字连接到服务器。

答案 1 :(得分:0)

尝试在脚本中添加一个sleep命令,以便让数据库有足够的时间正确启动。

答案 2 :(得分:0)

根据hub.docker.com/_/postgres上的文档,要添加自定义脚本以在容器启动时运行,请创建一个类似于以下内容的shell脚本,并创建一个自定义Dockerfile,您将在其中复制该Shell脚本进入/docker-entrypoint-initdb.d/

假设您将以下脚本作为initdatabase.sh保存在与以下示例中定义的自定义Dockerfile相同的文件夹中,那么在构建映像时,您将创建运行以下定义的以下sql语句的自定义映像。

#!/bin/bash
set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE USER user;
    CREATE DATABASE customdatabase;
    GRANT ALL PRIVILEGES ON DATABASE bloodapp TO user;
    // add other sql statements here
EOSQL
FROM mdillon/postgis:9.6-alpine

COPY initdatabase.sh /docker-entrypoint-initdb.d/