postgres 和 docker compose:在额外初始化后将服务状态更改为就绪

Sim*_*tis 6 django postgresql docker docker-compose

就我而言,postgres 数据库作为主要的 django 后端数据库。需要额外的 postgres 初始化。问题是postgres服务状态ready在额外的数据库初始化之前就变成了。因此,依赖的 django 应用程序在数据库初始化之前开始运行。

postgres有没有办法以额外初始化后的方式配置服务ready

docker-compose.yml

version: "3.3"

services:
  postgres:
    image: library/postgres:11
    volumes:
      - some_folder:/docker-entrypoint-initdb.d

  django_app:
    image: custom_django_image:latest
    volumes:
      - $PWD:/app
    ports:
      - 8000:8000
    depends_on:
      - postgres
Run Code Online (Sandbox Code Playgroud)

asc*_*lex 3

some_folder的 映射到 Postgres 容器的/docker-entrypoint-initdb.d位置是您(并且看起来您正在做的)应该放置初始化脚本的位置。只要附加到 Postgres 容器/var/lib/postgresql/data目录的可能卷中没有数据(持久数据),在创建容器时,Postgres 将首先运行这些脚本,然后再将 Postgres 设置为状态ready。脚本必须是.sh.sql文件。(文档)。我将展示我使用的典型工作流程:

我有这个创建多个数据库的脚本:

# create-multiple-databases.sh

set -e
set -u

function create_user_and_database() {
    local database=$1
    echo "  Creating user and database '$database'"
    psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
        CREATE USER $database;
        CREATE DATABASE $database;
        GRANT ALL PRIVILEGES ON DATABASE $database TO $database;
EOSQL
}

if [ -n "$POSTGRES_MULTIPLE_DATABASES" ]; then
    echo "Multiple database creation requested: $POSTGRES_MULTIPLE_DATABASES"
    for db in $(echo $POSTGRES_MULTIPLE_DATABASES | tr ',' ' '); do
        create_user_and_database $db
    done
    echo "Multiple databases created"
fi

Run Code Online (Sandbox Code Playgroud)

在我设置的文件中docker-compose.yml

environment:
  - POSTGRES_MULTIPLE_DATABASES=dev,test
Run Code Online (Sandbox Code Playgroud)

现在运行时docker-compose up,我看到脚本的输出,最后:

postgres_1            | CREATE DATABASE
postgres_1            | GRANT
postgres_1            | Multiple databases created
...
postgres_1            | PostgreSQL init process complete; ready for start up.
postgres_1            |
postgres_1            | 2020-05-23 16:18:40.055 UTC [1] LOG:  starting PostgreSQL 12.2 (Debian 12.2-2.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
postgres_1            | 2020-05-23 16:18:40.056 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres_1            | 2020-05-23 16:18:40.056 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres_1            | 2020-05-23 16:18:40.063 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
Run Code Online (Sandbox Code Playgroud)

现在,在我的 Django 应用程序中的一个典型settings.py文件(或类似的相关设置文件)中,我创建了一个 while 循环,该循环仅在数据库准备就绪后才完成。完成后,Django 服务器将继续其初始化过程,然后开始运行服务器。

while True:
    from django.db import connections
    from django.db.utils import OperationalError
    conn = connections["default"]  # or some other key in `DATBASES`
    try:
        c = conn.cursor()
        LOGGER.info("Postgres Ready")
        break
    except OperationalError:
        LOGGER.warning("Postgres Not Ready...")
        time.sleep(0.5)
Run Code Online (Sandbox Code Playgroud)

如果我理解了您的问题,我希望这能为您提供问题中所需的信息。