Не удается создать расширение pg_cron в docker-entrypoint-initdb.d

Если я создаю расширение pg_cron в docker-entrypoint-initdb.d/init.sql файл, образ докера не запускается и docker logs <id> просто говорит "Нет такого контейнера". Вот соответствующий фрагмент.sql:

CREATE DATABASE my_database;
\c my_database;
CREATE EXTENSION IF NOT EXISTS postgis CASCADE;
CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
CREATE EXTENSION IF NOT EXISTS pg_cron CASCADE;

Тем не менее, если я создаю расширение pg_cron после завершения команды docker run (т.е. удалите последнюю строку выше и запустите ее отдельно с psql --file после docker run завершается), расширение создается успешно (расширения postgis и timescaledb кажутся нормальными независимо).

Есть ли причина, по которой я не могу создать расширение pg_cron из docker-entrypoint-init.d? Есть ли правильное место?

Моя команда запуска Docker выглядит следующим образом:

 docker run -d \
        --name my_container --rm \
        -p 5432:5432 \
        -clog_line_prefix="%m [%p]: [%l-1] %u@%d" \
        -clog_error_verbosity=VERBOSE \
        -cshared_preload_libraries='timescaledb,pg_cron' \
        -ccron.database_name='my_database'

3 ответа

pg_cron может быть загружен только как общая библиотека. Вы должны указать это в postgres.conf файл. Поскольку все сценарии в docker-entrypoint-init.d выполняются после запуска сервера postgres (с pg_ctl start), все изменения shared_preload_libraries в postgres.conf может стать доступным после перезапуска (с pg_ctl restart).

Пример из реального мира:

002-setup.sh:

#!/bin/sh

# Remove last line "shared_preload_libraries='citus'"
sed -i '$ d' ${PGDATA}/postgresql.conf

cat <<EOT >> ${PGDATA}/postgresql.conf
shared_preload_libraries='pg_cron,citus'
cron.database_name='${POSTGRES_DB:-postgres}'
EOT

# Required to load pg_cron
pg_ctl restart

003-main.sql:

CREATE EXTENSION pg_cron;

Обратите внимание:

  1. порядок выполнения скрипта имеет значение и упорядочен по именам файлов
  2. pg_cron становится доступным в БД, указанном с cron.database_name

Предлагаемое решение не сработало для меня с вновь созданным контейнером. Итак, я сделал это так:

Файл Docker

      FROM postgres:13.2

RUN apt-get update && apt-get -y install git build-essential postgresql-server-dev-13

RUN git clone https://github.com/citusdata/pg_cron.git
RUN cd pg_cron && make && make install

RUN cd / && \
        rm -rf /pg_cron && \
        apt-get remove -y git build-essential postgresql-server-dev-13 && \
        apt-get autoremove --purge -y && \
        apt-get clean && \
        apt-get purge

COPY init-db /docker-entrypoint-initdb.d

init-db / 002-pg-cron.sh

      #!/usr/bin/env bash

# use same db as the one from env
dbname="$POSTGRES_DB"

# create custom config
customconf=/var/lib/postgresql/data/custom-conf.conf
echo "" > $customconf
echo "shared_preload_libraries = 'pg_cron'" >> $customconf
echo "cron.database_name = '$dbname'" >> $customconf
chown postgres $customconf
chgrp postgres $customconf

# include custom config from main config
conf=/var/lib/postgresql/data/postgresql.conf
found=$(grep "include = '$customconf'" $conf)
if [ -z "$found" ]; then
  echo "include = '$customconf'" >> $conf
fi

Кроме того, вы можете поместить другие файлы инициализации в каталог init-db.

003-main.sql

      CREATE EXTENSION pg_cron;

Docker создать файл

      version: '3.7'
services:
  postgres:
    container_name: your-container
    build: .
    environment:
      POSTGRES_DB: "your_db"
      POSTGRES_USER: "your_user"
      POSTGRES_PASSWORD: "your_user"
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"
volumes:
  pgdata:
    driver: local

Вам необходимо установить и настроить pg_cron расширение.

Я рекомендую вам использовать (или хотя бы разветвить) этот репозиторий: ramazanpolat / postgres_cron: Dockerfile для сборки postgresql:11 с расширением pg_cron

Другие вопросы по тегам