Bash 如何在ENTRYPOINT中等待postgres启动?

Bash 如何在ENTRYPOINT中等待postgres启动?,bash,postgresql,docker,Bash,Postgresql,Docker,在继续执行nosetests之前,等待postgres在我的ENTRYPOINT内完全启动的最佳方法是什么 现在,我已经将机器的启动时间定在50秒左右。所以我只睡了60秒。这感觉不好,因为在另一台机器上运行时可能不起作用 ENTRYPOINT \ runuser -l postgres -c '/usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main -c config_file=/etc/po

在继续执行
nosetests
之前,等待
postgres
在我的
ENTRYPOINT
内完全启动的最佳方法是什么

现在,我已经将机器的启动时间定在50秒左右。所以我只睡了60秒。这感觉不好,因为在另一台机器上运行时可能不起作用

ENTRYPOINT \
           runuser -l postgres -c '/usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main -c config_file=/etc/postgresql/9.3/main/postgresql.conf & ' && \
           sleep 60 && \
           nosetests --verbose --cover-erase --with-coverage --cover-package=stalker
这是启动postgres的输出:

2017-02-13 13:46:49.541 UTC [9] LOG:  database system was interrupted; last known up at 2017-02-13 12:53:23 UTC
2017-02-13 13:47:37.951 UTC [9] LOG:  database system was not properly shut down; automatic recovery in progress
2017-02-13 13:47:37.994 UTC [9] LOG:  redo starts at 0/1783EA0
2017-02-13 13:47:37.995 UTC [9] LOG:  record with zero length at 0/17841E8
2017-02-13 13:47:37.995 UTC [9] LOG:  redo done at 0/17841B8
2017-02-13 13:47:37.995 UTC [9] LOG:  last completed transaction was at log time 2017-02-13 12:53:23.731984+00
2017-02-13 13:47:38.384 UTC [9] LOG:  MultiXact member wraparound protections are now enabled
2017-02-13 13:47:38.387 UTC [7] LOG:  database system is ready to accept connections
2017-02-13 13:47:38.387 UTC [13] LOG:  autovacuum launcher started

请注意,我明白这违反了在
入口点
中运行多个命令的惯例。在这种情况下,我有充分的理由这样做。

我通常会使用一个小的“tcp端口等待”脚本,如下所示:

#/bin/bash
set-e
如果[-z“$1”-o-z“$2”]
然后
echo“tcp端口等待-阻止,直到指定的tcp端口变为可用”
echo“用法:ntcp端口等待主机端口”
出口1
fi
echo正在等待端口$1:$2可用。。。
虽然nc-z$1$2>/dev/null
做
让经过=经过+1
如果[“$已用”-gt 90]
然后
echo“超时!”
出口1
fi
睡眠1;
完成
回声“准备好了!”
等待某项服务启动并准备就绪

对于Postgresql,它将侦听的默认端口为5432,因此命令为:

tcp-port-wait localhost 5432
这将一直阻止,直到Postgresql服务准备好为容器内的环回接口上的:5432上的连接提供服务(在入口点脚本的上下文中运行时)

您当然必须将此脚本复制到您的容器中, 通过在Dockerfile中添加类似的行:

在你可以使用它之前

并安装netcat实用程序

您也可以将其用于其他类型的服务,如Tomcat或Mysql

如果需要,您也可以在“容器外”等待,如下所示:

docker exec my_容器tcp端口等待本地主机5432

请注意,当然还有其他方法可以做到这一点,例如使用某种编排工具,如docker compose with,或容器内部的某个流程管理器。

感谢@zeppelin建议
pg\u isready
。我最后用了这个:

#!/bin/bash
# wait-for-postgres.sh

set -e

cmd="$@"
timer="5"

until runuser -l postgres -c 'pg_isready' 2>/dev/null; do
  >&2 echo "Postgres is unavailable - sleeping for $timer seconds"
  sleep $timer
done

>&2 echo "Postgres is up - executing command"
exec $cmd
我在我的
入口点中使用这个:

ENTRYPOINT \

            # Start PostgreSQL
            runuser -l postgres -c '/usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main -c config_file=/etc/postgresql/9.3/main/postgresql.conf & ' && \

            # Exectute tests when db is up
            ./wait-for-postgres.sh nosetests --verbose --cover-erase --with-coverage --cover-package=stalker

您可以在返回代码为1时在循环中运行。嗯,这很奇怪,显然它在恢复过程中接受连接,请尝试将
nc-z$1$2
替换为
pg_isready
(这是一个用于检查其状态的PostgreSQL特定实用程序),并查看它是否有帮助。谢谢,使用
pg_isready
工作了!此外,我还必须删除对参数的检查。如果你想修改你的答案,我会把它标记为接受。
ENTRYPOINT \

            # Start PostgreSQL
            runuser -l postgres -c '/usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main -c config_file=/etc/postgresql/9.3/main/postgresql.conf & ' && \

            # Exectute tests when db is up
            ./wait-for-postgres.sh nosetests --verbose --cover-erase --with-coverage --cover-package=stalker