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.
Прочитав это, я начну с консолидации всех ваших зависимостей.