2017-02-13 38 views
6

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

现在我已经在我的机器上启动了大约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 

请,我不明白,这不利于在ENTRYPOINT运行多个命令的约定。在这种情况下,我有很好的理由这样做。

+1

您可以运行['pg_isready'](https://www.postgresql.org/docs/current /static/app-pg-isready.html),而返回代码为1. –

回答

0

最好不要在一个容器中运行多个东西。最好的办法是让你postgres运行在一个容器中,并有另一个为你的nosetests

您可以创建一个docker-compose文件,其中nosetest“依赖于”数据库。

+0

_depends_只是强制启动容器的顺序,但postgress容器已启动的事实并不意味着它已准备就绪接受连接(即准备测试),因此您还必须使用正确的[healthcheck](https://docs.docker.com/compose/compose-file/#/healthcheck)来验证_postgress_进程containe r真的准备好了。 – zeppelin

+0

这是一个非常好的观点,我不知道如何让它走。另外,虽然我支持我的观点100%,但这并不是一个完全的答案,因为它实际上并没有解决问题。 – Nanne

1

我通常会用一个小的“TCP端口,等待”的剧本,是这样的:

#!/bin/bash 
set -e 

if [ -z "$1" -o -z "$2" ] 
then 
    echo "tcp-port-wait - block until specified TCP port becomes available" 
    echo "Usage: ntcp-port-wait HOST PORT" 
    exit 1 
fi 
echo Waiting for port $1:$2 to become available... 
while ! nc -z $1 $2 2>/dev/null 
do 
    let elapsed=elapsed+1 
    if [ "$elapsed" -gt 90 ] 
    then 
     echo "TIMED OUT !" 
     exit 1 
    fi 
    sleep 1; 
done 

echo "READY !" 

要等到一定的服务和准备。

在PostgreSQL的情况下,它会监听的默认端口是,所以命令为:

tcp-port-wait localhost 5432 

这将阻塞,直到PostgreSQL服务已准备好为连接上:5432上容器内部的回送接口(当在ENTRYPOINT脚本的上下文中运行时)。

你肯定有通过添加这样的一条线,你Dockerfile这个脚本复制到你的容器, :

COPY tcp-port-wait /usr/local/bin/ 

,然后才能使用它。

并且还安装netcat实用程序。

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

而且,如果你需要,你也可以等待“容器外”,类似这样的:

docker exec my_container tcp-port-wait localhost 5432 

注意,也肯定有其他方法可以做到这一点,例如通过使用一些编排工具,如码头组成healthcheck directive,或一些流程管理器内的容器本身。

+0

这看起来不错,但对我来说,这个脚本立即认为数据库已启动:http://pastebin.com/x8UwhHQD – fredrik

+0

嗯,这很奇怪,显然它正在接受连接,同时恢复正在进行中,尝试更换'nc - z $ 1 $ 2'与'pg_isready'(这是一个PostgreSQL特定的工具来检查它的状态),看看它是否有帮助。 – zeppelin

+0

谢谢,使用'pg_isready'工作!另外,我必须删除参数的检查。如果您想修改答案,我会将其标记为已接受。 – fredrik

7

感谢@zeppelin建议pg_isready。最后我用这样的:在我的ENTRYPOINT

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

set -e 

cmd="[email protected]" 
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