Postgres with Docker: Postgres не загружается при сохранении данных

Я новичок в Postgres.

Я обновил файл Docker, который я использовал и успешно установил Postgresql на нем. (Мое изображение работает Ubuntu 16.04, и я использую Postgres 9.6.)

Все работало нормально, пока я не попытался переместить базу данных в Volume с помощью docker-compose (после создания копии папки с контейнером с cp -R /var/lib/postgresql /somevolume/.)

Проблема в том, что Postgres просто продолжает сбой, о чем свидетельствует супервизор:

2017-07-26 18:55:38,346 INFO exited: postgresql (exit status 1; not expected)
2017-07-26 18:55:39,355 INFO spawned: 'postgresql' with pid 195
2017-07-26 18:55:40,430 INFO success: postgresql entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2017-07-26 18:55:40,763 INFO exited: postgresql (exit status 1; not expected)
2017-07-26 18:55:41,767 INFO spawned: 'postgresql' with pid 197
2017-07-26 18:55:42,841 INFO success: postgresql entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2017-07-26 18:55:43,179 INFO exited: postgresql (exit status 1; not expected)
(and so on…)

Журналы

Мне не ясно, что происходит, когда /var/log/postgresql остается пустым.

Чаун?

Я подозреваю, что это связано с пользователем. Если я сравниваю папку данных внутри контейнера и копию, которую я сделал с этим томом, единственное отличие состоит в том, что оригинал принадлежит postgres, а копия принадлежит root.

Я попытался запустить chown -R postgres:postgres в копии. Операция была выполнена успешно, однако postmaster.pid остается в собственности root, и я думаю, что это будет проблемой.

Вопросы

  • Как получить дополнительную информацию о причине сбоя?
  • Как я могу сделать так, чтобы postmaster.id принадлежал postgres?
  • Должен ли я считать запуск postgres с помощью root?

Любые приветствия.


EDIT: ссылки на файл Docker и docker-compose.xml.

Ответ 1

Я отвечу на свой вопрос:

Журналы и ошибки

Что усложнило ситуацию, так это то, что я не получал никаких сообщений об ошибке.

Чтобы изменить это, я отключил раздел [program:postgresql] в супервизоре и вместо этого начал вручную запускать postgres из командной строки (спасибо Miguel Marques за то, что он установил меня на правильном пути с его комментарием.)

Затем я наконец получил несколько полезных сообщений об ошибках:

2017-08-02 08:27:09.134 UTC [37] LOG:  could not open temporary statistics file "/var/run/postgresql/9.6-main.pg_stat_tmp/global.tmp": No such file or directory

Фиксация конфигурации

Я исправил вышеприведенную ошибку, добавив их в мой Dockerfile:

mkdir -p /var/run/postgresql/9.6-main.pg_stat_tmp
chown postgres.postgres /var/run/postgresql/9.6-main.pg_stat_tmp -R

(Kudos to этот парень для исправления.)

Чтобы сделать данные постоянными, я также должен был сделать это, чтобы доступ к тому был доступен postgres:

mkdir -p /var/lib/postgresql/9.6/main
chmod 700 /var/lib/postgresql/9.6/main 

Я также использовал initdb для инициализации каталога данных. BEWARE! Это приведет к удалению любых данных, найденных в этой папке. Например:

rm -R /var/lib/postgresql/9.6/main/*
ls /var/lib/postgresql/9.6/main/
/usr/lib/postgresql/9.6/bin/initdb  -D /var/lib/postgresql/9.6/main

Тестирование

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

su postgres
/usr/lib/postgresql/9.6/bin/postgres -D /var/lib/postgresql/9.6/main -c config_file=/etc/postgresql/9.6/main/postgresql.conf # as per the Docker docs

Чтобы протестировать, я продолжал работать, а затем из другого приглашения проверял, что все работает нормально:

su postgres
psql
CREATE TABLE cities ( name varchar(80), location point );
INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)');
select * from cities; # repeat this command after restarting the container to check that the data does persist

... убедитесь, что перезагрузили контейнер и снова проверили, чтобы проверить, что данные сохранялись.

И затем, наконец, восстановил раздел [program:postgresql] в супервизоре, восстановил изображение и перезапустил контейнер, убедившись, что все работает нормально (в частности supervisord: tail /var/log/supervisor/supervisord.log), что и было.

(Команда, которую я использовал внутри supervisord.conf, также /usr/lib/postgresql/9.6/bin/postgres -D /var/lib/postgresql/9.6/main -c config_file=/etc/postgresql/9.6/main/postgresql.conf, согласно этой статье Docker и другим примерам postgres + supervisord. Другие варианты использовали бы pg_ctl или init.d script, но мне непонятно, почему/когда их использовать.)


Я потратил много времени на это. Надеюсь, что подробный ответ поможет кому-то по очереди.

P.S.: Я в конечном итоге создал минимальный пример моей проблемы. Если это может кому-то помочь, вот они: Dockerfile, supervisord.conf и docker-compose.yml.

Ответ 2

Я не знаю, будет ли это другим способом добиться того же результата (я тоже новичок в Docker и Postgres), но вы попробовали официальный образ репозитория для Postgres (https://hub.docker.com/_/postgres/)?

Я получаю данные из контейнера, устанавливая переменную окружения PGDATA в '/var/lib/postgresql/data/pgdata' и привязывая ее к внешнему тому в команде запуска:

docker run --name bd_TEST --network=my_network --restart=always -e POSTGRES_USER="superuser" -e POSTGRES_PASSWORD="myawesomepass" -e PGDATA="/var/lib/postgresql/data/pgdata" -v /var/local/db_data:/var/lib/postgresql/data/pgdata -itd -p 5432:5432 postgres:9.6

Когда том пуст, все файлы создаются при запуске образа script, и если они уже существуют, база данных начнет использовать его.

Ответ 3

Из прошлого опыта я вижу, что может быть проблемой. Я не могу сказать, поможет ли это, но стоит попробовать. Я бы добавил это как комментарий, но я не могу, потому что мой представитель не достаточно высок.

Я обнаружил пару проблем с тем, как вы структурировали свои утверждения в своем файле Docker. Вы устанавливали различные вещи несколько раз, а также обновлялись спорадически через код. В моих собственных файлах я заметил, что это может привести к некоторому случайному поведению моих сервисов и установке из-за разных слоев.

Возможно, это не поможет решить вашу проблему напрямую, но очистка вашего файла, как описано в лучших практиках, решила многие проблемы Dockerfile для меня в прошлом.

Одно из первых мест для поиска таких проблем - начать здесь, в лучшие практики для RUN. Это помогло мне решить сложные проблемы в прошлом, и я надеюсь, что это решит или, по крайней мере, упростит.

Обратите особое внимание на эту часть:

После создания изображения все слои находятся в кеше Docker. Предположим, что вы позже модифицируете apt-get install, добавив дополнительный пакет:

 FROM ubuntu:14.04
 RUN apt-get update
 RUN apt-get install -y curl nginx 

Докер видит исходные и измененные инструкции как идентичные и повторно использует кеш из предыдущего шаги. В результате обновление apt-get НЕ выполняется, поскольку build использует кешированную версию. Поскольку обновление apt-get не выполняется, ваша сборка может потенциально получить устаревшую версию завитка и nginx.

Прочитав это, я начну с консолидации всех ваших зависимостей.