【问题标题】:Docker - check if postgres is readyDocker - 检查 postgres 是否准备好
【发布时间】:2018-03-12 23:56:26
【问题描述】:

我有一个 Kong API Gateway 容器和一个 postgres 容器,我需要在运行迁移之前检查 postgres 是否已从 Kong 容器启动并准备就绪。我正在考虑将 postgres 客户端实用程序安装到基于官方 Kong 映像的自定义映像中,在我的 Dockerfile 中使用 RUN yum install postgresql -y && yum clean all 并使用 psqlpg_isready 来实现此目的。我创建了一个名为polling 的postgres 用户,密码为空,专门用于通过这两个实用程序检查服务器的状态。它们都不起作用。

我尝试从自定义 Kong 图像执行这些命令:

  1. psql。命令 psql -h postgres -U polling -w -c '\l' 失败并出现错误 psql: fe_sendauth: no password supplied。但是用户没有密码。我究竟做错了什么?使用 psql 检查服务器是否准备就绪的完整 shell 脚本描述为 here

  2. pg_isready。我不知道如何将此实用程序单独安装到基于官方 Kong 映像的自定义映像中,该映像又基于 centos:7 映像,postgresql 包不包括 pg_isready。仅安装了这些实用程序并且可以在/usr/bin 中找到:pg_configpg_dumppg_dumpallpg_restorepsql。如何安装pg_isready?我不想在 Kong 映像中安装完整的服务器。

【问题讨论】:

  • 关于#1,你调整了pg_hba.conf吗?见dba.stackexchange.com/questions/83164/…
  • @bluescores 对,我需要更改此配置或在客户端上添加 .pgpass。解决了后者的问题。我应该注意到我必须为我的投票用户设置密码,如果 pass 是空的,psql 会对我大喊,不管 .pgpass

标签: postgresql docker centos kong


【解决方案1】:

我们通过对端口 5432 进行简单的 TCP 检查来解决这个问题,而无需任何 PG 工具。我们只使用wait-for-it.sh,效果很好。 Postgres 在服务器真正准备好服务之前不会打开端口,所以这显然没问题。

示例 Dockerfile:https://github.com/apim-haufe-io/wicked.kong/blob/master/Dockerfile

对应的启动脚本(只有最后一行对这个特定问题感兴趣):https://github.com/apim-haufe-io/wicked.kong/blob/master/startup.sh

片段:

wait-for-it.sh -h $KONG_PG_HOST -p 5432 -t 30 -- kong start --run-migrations

等一下:https://github.com/vishnubob/wait-for-it

【讨论】:

  • 这在您必须第一次在容器中启动 postgres 时不起作用,因为服务器将准备好并尝试运行启动脚本。我收到了对服务器的请求,导致初始化脚本不幸崩溃。
  • 同意@jemiloii。该端口在 Postgres 准备好运行脚本之前可用
  • 我也偶尔看到过这种情况,但并不常见。在某些地方,我还看到了 sleep 5 在等待它返回后,这通常就足够了。腰带和吊带会要求 runnint wait-for-it、sleep、wait-for-it。通常对我来说已经足够了。
【解决方案2】:

我的解决方案是基于官方 kong 图像创建一个新图像,并像这样覆盖入口点:

#!/usr/bin/env bash
set -e

# Disabling nginx daemon mode
export KONG_NGINX_DAEMON="off"

# Setting default prefix (override any existing variable)
export KONG_PREFIX="/usr/local/kong"

# Prepare Kong prefix
if [ "$1" = "/usr/local/openresty/nginx/sbin/nginx" ]; then
    kong prepare -p "/usr/local/kong"
fi

#waiting for postgres
until psql --host=$KONG_PG_HOST --username=$POLLING_USER $POLLING_DATABASE -w &>/dev/null
do
  echo "Waiting for PostgreSQL..."
  sleep 1
done

echo "Postgres is ready, running the migrations..."

kong migrations up

echo "READY TO START UP KONG USING CMD" $@;

exec "$@"

【讨论】:

    【解决方案3】:

    我尝试了等待它,但是在 docker 容器中运行它可能会出现问题,因为在 docker 映像中可能没有安装 nc(有时甚至没有 ping、telnet、curl..)。因此,为了检查数据库是否已启动并运行,我在 docker compose 文件中使用了 HealthCheck 来检查 pg_isready 的返回值,它是 postgres 数据库的一部分,因此您无需在 docker 映像中安装任何东西:

    version: '2.3'
    services:
      postgres-db:
        image: postgresImage
        healthcheck:
          test: /usr/bin/pg_isready
          interval: 5s
          timeout: 10s
          retries: 120
        ports:
          - '5432:5432'
    
      aplication:
        image: applicationImage
        depends_on:
          postgres-db:
            condition: service_healthy
    

    【讨论】:

    【解决方案4】:

    这是一个使用 PostgreSQL 提供的pg_isready 工具的shell one liner。

    调用外部 docker:

    DOCKER_CONTAINER_NAME="mypgcontainer"
    timeout 90s bash -c "until docker exec $DOCKER_CONTAINER_NAME pg_isready ; do sleep 5 ; done"
    

    Based on a post from Jeroma Belleman.

    【讨论】:

    • 我很惊讶这个答案没有得到更多的支持。我得出了同样的结论,它确实适用于pg_isready,而不适用于“wait for-it.sh”bash 脚本,因为 TCP 端口在 postgres 真正准备好“工作”之前已经准备好。否则,您可能会收到如下错误:An exception occurred in driver: SQLSTATE[08006] [7] server closed the connection unexpectedly.
    • 这是一个新的答案。
    猜你喜欢
    • 2017-07-22
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    相关资源
    最近更新 更多