Docker - 检查 postgres 是否准备好

问题描述 投票:0回答:5

我有一个 Kong API Gateway 容器和一个 postgres 容器,我需要在运行迁移之前检查 postgres 是否已从 Kong 容器启动并准备就绪。我正在考虑使用 Dockerfile 中的

RUN yum install postgresql -y && yum clean all
将 postgres 客户端实用程序安装到基于官方 Kong 映像的自定义映像中,并使用
psql
pg_isready
来实现此目的。我创建了一个名为
polling
的 postgres 用户,密码为空,专门用于通过这两个实用程序检查服务器的状态。他们都不起作用。

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

  1. psql。命令

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

  2. pg_isready。我不知道如何将此实用程序单独安装到基于官方 Kong 映像的自定义映像中,而该映像又基于

    centos:7
    映像,
    postgresql
    包不包含
    pg_isready
    。仅安装了这些实用程序,并且可以在
    /usr/bin
    中找到:
    pg_config
    pg_dump
    pg_dumpall
    pg_restore
    psql
    。如何安装
    pg_isready
    ?我不想在 Kong 映像中安装完整的服务器。

postgresql docker centos kong
5个回答
68
投票

这是一个使用 PostgreSQL 提供的

pg_isready
工具的 shell oneliner。

调用外部码头工人:

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

基于 Jeroma Belleman 的帖子


23
投票

我尝试等待它,但在 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

8
投票

我们通过在端口 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


7
投票

我的解决方案是基于官方 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 "$@"

0
投票

正如几个答案提到的,使用

pg_isready
是实现此目的的好方法。

但是,如果您的图像可能正在通过

/docker-entrypoint-initdb.d
中的脚本加载数据或执行其他初始化工作,那么即使数据库尚未真正“准备好”,此测试也会在该阶段成功。

为了避免这种情况,请将

-h localhost
添加到
pg_isready
调用中。在初始化过程中,postgres 只能通过 UNIX 套接字使用,因此测试将会失败,直到服务器在包含 TCP 访问的“生产”配置中关闭并重新启动。

© www.soinside.com 2019 - 2024. All rights reserved.