【问题标题】:How to wait for postgres startup in ENTRYPOINT?如何在 ENTRYPOINT 等待 postgres 启动?
【发布时间】:2017-07-01 13:27:56
【问题描述】:

在继续执行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

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

【问题讨论】:

  • 您可以在返回码为 1 时循环运行 pg_isready

标签: bash postgresql docker


【解决方案1】:

我通常会使用一个小的“tcp-port-wait”脚本,像这样:

#!/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,它会监听的默认端口是 5432,所以命令是:

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 directivedocker-compose,或者容器本身内部的一些进程管理器。

【讨论】:

  • 嗯,这很奇怪,显然它在恢复过程中接受连接,尝试用 pg_isready 替换 nc -z $1 $2(这是一个 PostgreSQL 特定的实用程序,用于检查它的状态),然后查看如果有帮助的话。
  • 谢谢,使用pg_isready 成功了!此外,我不得不删除对参数的检查。如果您想修改答案,我会将其标记为已接受。
【解决方案2】:

感谢@zeppelin 建议pg_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 中使用它:

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

【讨论】:

    猜你喜欢
    • 2021-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    相关资源
    最近更新 更多