我有一些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当容器启动但是如果从容器手动连接它连接成功?
谢谢!
答案 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/