我想使用Docker将.sql文件加载到PostgreSQL数据库并提供服务。
以下命令快速返回(在数据库完全填充之前 - 它似乎在后台异步发生)。
docker run \
--name myContainer \
-p 5432:5432 \
-v mySqlFile.sql:/docker-entrypoint-initdb.d/dump.sql \
-d postgres:alpine
由于此命令将成为脚本的一部分,因此我希望阻止该命令,直到数据库完全初始化为mySqlFile.sql
在加载mySqlFile.sql
时,如何获取阻止命令或其他暂停方法?
为清楚起见:我运行上面的命令,然后执行以下命令:
echo "select count(*) as \"Posts imported\" from posts;" | docker exec -i myContainer psql -U postgres
Posts imported
----------------
0
(1 row)
等了几秒钟,我明白了:
echo "select count(*) as \"Posts imported\" from posts;" | docker exec -i myContainer psql -U postgres
Posts imported
----------------
51103
(1 row)
这是一个问题,因为我希望构建一个自动化解决方案。我希望docker run命令阻止,直到所有记录都已导入Postgres。然后我让数据库处于准备好下一个命令的状态。
答案 0 :(得分:3)
创意:创建一个自定义包装器,在填充脚本的末尾等待插入表中的特定记录。
使用docker-compose
您可以使用自定义包装脚本:
在docker-compose.yml
中version: "2"
services:
app:
build: app/
depends_on:
- "db"
command: ["./wait-for-postgres.sh", "db", "yourcommand", "with", "parameters"]
db:
build: db/
在wait-for-postgres.sh
#!/bin/bash
# wait-for-postgres.sh
set -e
host="$1"
shift
cmd="$@"
#wait postgres up
until psql -h "$host" -U "postgres" -c '\q'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done
#wait populate script
while ! psql -h "$host" -U "postgres" -t -c "select * from docker_ready" | egrep .
do
sleep 1
done
>&2 echo "Postgres is populated - executing command"
exec $cmd
您可以在https://docs.docker.com/compose/startup-order/找到一些提示, https://hub.docker.com/_/postgres/
答案 1 :(得分:2)
我找到了解决方案。我想你可以用这种方式。
运行postgres
图像时,ENTRYPOINT是一个shell。
如果您运行ps aux
,则会看到PID 1
为bash
。
但是,当所有初始化完成后,postgres
成为exec "$@"
的主要流程。该时间 PID 1
为postgres
。
你可以使用这个黑客。您不知道何时完成初始化。但您确信,初始化完成后, PID 1
将为postgres
。
$ docker exec -i myContainer ps -p 1 -o comm=
初始化运行时,这将返回bash
。一切都完成后将更改为postgres
。
当然,你需要循环。但是通过这种方式,你可以确定初始化完全没有任何猜测。
<强>更新强>
当您使用高山图像时,它已切割ps
版本。您需要在高山图像中安装未剪切的ps
。 (堆栈溢出question)
首先运行以下命令。
$ docker exec -i myContainer apk add --no-cache procps
现在ps -p 1 -o comm=
可以使用
希望这会有所帮助