Как исправить ошибки выполнения Pups при запуске Discourse

Я создаю новый экземпляр Discourse с нуля в целях разработки и снова вижу ошибку загрузки:

FAILED
--------------------
Pups::ExecError: cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate' failed with return #<Process::Status: pid 1002 exit 1>
Location of failure: /usr/local/lib/ruby/gems/3.3.0/gems/pups-1.2.1/lib/pups/exec_command.rb:132:in `spawn'
exec failed with the params {"cd"=>"$home", "tag"=>"migrate", "hook"=>"db_migrate", "cmd"=>["su discourse -c 'bundle exec rake db:migrate'"]}
bootstrap failed with exit code 1

Настройка контейнеров включает два контейнера: webonly и dataonly (redis), а также внешнюю базу данных PostgreSQL. Закомментирование настроек MaxMind ничего не меняет.

Есть ли какие-либо идеи, что можно сделать в данной ситуации?

Наиболее вероятная причина — нехватка памяти. В таком случае добавьте файл подкачки или перейдите на экземпляр с большим объёмом оперативной памяти. Попробуйте выполнить команду free -h.

Хм, нет, у нас 4 ГБ ОЗУ и достаточно места на диске (2 × 32 ГБ), общая среда такая же, как на другой Docker-машине, где сборки работают без проблем.

Статус памяти:

root@docker3a:/var/discourse# free -h
всего использовано свободно совместно Буфер/Кэш доступный
Память: 3,8 ГиБ 819 МиБ 1,4 ГиБ 22 МиБ 1,9 ГиБ 3,0 ГиБ
Своп: 974 МиБ 52 МиБ 922 МиБ

Есть ли какие-либо недавние ошибки в выводе dmesg, которые могут быть relevant?

Можешь поделиться полным логом?

Странное предположение: в Discourse ошибки миграции из-за нехватки памяти (OoM) обычно не возникают.

Обнаружена архитектура x86_64.
Проверка актуальности лаунчера
Лаунчер актуален
2.0.20250226-0128: Получение образа из discourse/base
Сумма проверки: sha256:6f18aa2cd22bba0deb91d69194e577d4f96130ad555ae8ec646a8792cbfe37db
Статус: Образ discourse/base:2.0.20250226-0128 уже актуален
docker.io/discourse/base:2.0.20250226-0128
/usr/local/lib/ruby/gems/3.3.0/gems/pups-1.2.1/lib/pups.rb
/usr/local/bin/pups --stdin
18:C 19 апр 2025 16:38:41.670 # oO0OoO0OoO0Oo Redis запускается oO0OoO0OoO0Oo
18:C 19 апр 2025 16:38:41.670 # Версия Redis=7.0.15, биты=64, коммит=00000000, изменен=0, pid=18, только что запущен
18:C 19 апр 2025 16:38:41.670 # Конфигурация загружена
18:M 19 апр 2025 16:38:41.670 * Монохронные часы: POSIX clock_gettime
18:M 19 апр 2025 16:38:41.670 * Режим работы=standalone, порт=6379.
18:M 19 апр 2025 16:38:41.670 # Сервер инициализирован
18:M 19 апр 2025 16:38:41.671 * Загрузка RDB, созданного в версии 7.0.15
18:M 19 апр 2025 16:38:41.671 * Возраст RDB: 72606 секунд
18:M 19 апр 2025 16:38:41.671 * Использование памяти RDB при создании: 0.82 Мб
18:M 19 апр 2025 16:38:41.671 * Загрузка RDB завершена, ключей загружено: 0, ключей истекло: 0.
18:M 19 апр 2025 16:38:41.671 * БД загружена с диска за 0.000 секунд
18:M 19 апр 2025 16:38:41.671 * Готов к принятию соединений
999:C 19 апр 2025 16:39:59.006 # oO0OoO0OoO0Oo Redis запускается oO0OoO0OoO0Oo
999:C 19 апр 2025 16:39:59.006 # Версия Redis=7.0.15, биты=64, коммит=00000000, изменен=0, pid=999, только что запущен
999:C 19 апр 2025 16:39:59.006 # Конфигурация загружена
999:M 19 апр 2025 16:39:59.006 * Монохронные часы: POSIX clock_gettime
999:M 19 апр 2025 16:39:59.006 # Предупреждение: Не удалось создать TCP-сокет для прослушивания сервера *:6379: bind: Адрес уже используется
999:M 19 апр 2025 16:39:59.006 # Ошибка прослушивания порта 6379 (TCP), прерывание.
18:signal-handler (1745080813) Получен SIGTERM, планирование завершения работы...
18:M 19 апр 2025 16:40:13.541 # Пользователь запросил завершение работы...
18:M 19 апр 2025 16:40:13.541 * Сохранение финального снимка RDB перед выходом.
18:M 19 апр 2025 16:40:13.549 * БД сохранена на диск
18:M 19 апр 2025 16:40:13.549 # Redis готов к выходу, пока...


ОШИБКА
--------------------
Pups::ExecError: cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate' завершилась с ошибкой, код возврата #<Process::Status: pid 1002 exit 1>
Место возникновения ошибки: /usr/local/lib/ruby/gems/3.3.0/gems/pups-1.2.1/lib/pups/exec_command.rb:132:in `spawn'
Выполнение не удалось с параметрами {"cd"=>"$home", "tag"=>"migrate", "hook"=>"db_migrate", "cmd"=>["su discourse -c 'bundle exec rake db:migrate'"]}
Загрузка не удалась с кодом выхода 1
** НЕ УДАЛОСЬ ЗАПУСТИТЬ ** Пожалуйста, прокрутите вверх и поищите более ранние сообщения об ошибках, их может быть несколько.
./discourse-doctor может помочь диагностировать проблему.
48b8aa6c912bbabc42d6b9373808088f5aa9079de1e1f7360fc858891a48556b

Если это контейнер web_only, почему на нём запущен Redis?

Можете поделиться определениями ваших контейнеров в YAML? И зачем вообще вы используете установку из двух контейнеров?

Привет, Фалько!
Ты прав, а я глупый :wink:
Я исправлю это…

OK, я исправил разделение web_only и redis. Сейчас сообщение об ошибке выглядит так:

FAILED
--------------------
Pups::ExecError: cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate' failed with return #<Process::Status: pid 981 e
xit 1>
Location of failure: /usr/local/lib/ruby/gems/3.3.0/gems/pups-1.2.1/lib/pups/exec_command.rb:132:in `spawn'
exec failed with the params {"cd"=>"$home", "tag"=>"migrate", "hook"=>"db_migrate", "cmd"=>["su discourse -c 'bundle exec rake db:migra
te'"]}
bootstrap failed with exit code 1
** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.
./discourse-doctor may help diagnose the problem.
801049b69a89d38b1ae5c299d356fc5f8dc6a8f518b1260c2dde05e0b6081556

Но возможно, это недопонимание или недостаток знаний с моей стороны:

База данных должна быть внешней, находиться в другом контейнере LXC с PostgreSQL. Пользователь базы данных и сама база существуют, но перед первой инициализацией (bootstrap) контейнера web_only база данных пуста. Скрипт сам создаёт базу данных на удалённой системе при первой сборке? Или мне сначала нужно создать контейнер базы данных, а затем вручную экспортировать его схему по умолчанию и данные во внешний демон PostgreSQL?

Визуализация общей конфигурации

Спасибо за схему. Это довольно сложная настройка — так поступают только при наличии веской причины и хорошем знании местности.

Если вы всё ещё видите следующее, то это, скорее всего, указывает на проблему. Redis не может открыть порт, на котором ему нужно слушать запросы.

Так что вопросы следующие: должен ли Redis делать это в данном контейнере, и если да, то где ещё на машине запущен другой экземпляр Redis. Здесь может оказаться полезным инструмент lsof.

Привет, @Ed_S!
Спасибо за подсказку насчёт отсутствующего порта. Сначала я хочу дождаться ответа от Falco по моим вопросам относительно общей настройки Discourse с внешней базой данных PostgreSQL.

Да, настройка немного сложнее стандартной, где используется только один контейнер приложения. Я запускаю всё на выделенном root-сервере с Proxmox (https://proxmox.com) как средой виртуализации у hetzner.de.

Вам всё ещё нужно предоставить полные логи, включая часть, где произошла неудача миграции. Моё предположение (и это лишь предположение, так как вы не предоставили ошибку) заключается в том, что вы используете плагин AI, а в вашей базе данных отсутствует необходимый аддон.

Нет, это установка без плагина AI, хотя этот экземпляр в будущем станет полигоном для функций AI.

Во вложении архив с

./launcher bootstrap web_only >> web_only_bootstrap.log

и файлами yml для redis и web_only, пароли удалены.

forum2_build.tar.gz (3.3 КБ)

Longshot:

links:
  - link:
      name: redis
      alias: data

почему здесь не alias: redis?

В файле из /samples/web_only.yml указано:

# Используйте ключ 'links' для связывания контейнеров, то есть используйте флаг Docker --link.
links:
- link:
name: data
alias: data

В моём случае контейнер data — это контейнер redis:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
a27999b28a90 local_discourse/redis "/sbin/boot" 2 days ago Up 20 hours

следовательно name: redis и alias: data.

Согласно документации Docker, это устаревшая функция, но она всё ещё работает, см. Legacy container links | Docker Docs

Теперь я считаю, что лучшим подходом будет сначала создать стандартную настройку «всё в одном» (app.yml). Затем сделать дамп SQL начальной схемы и данных из контейнера во внешний сервер PostgreSQL. @Falco, что ты думаешь?

Но в нём всего 28 строк, значит, большинство из них отсутствует.

Мое новое предположение: он вообще не обращается к вашей базе данных, хотя возможно, что проблема в Redis, с которым он не связывается.

Попробуйте

./launcher bootstrap web_only >> web_only_bootstrap.log 2>&1

Установщик автоматически создаст всё необходимое, если ему будут предоставлены действительные учётные данные и если он сможет подключиться к базе данных. Это описано в статье Настройка Discourse для использования отдельного сервера PostgreSQL

web_only_bootstrap2.tar.gz (9,1 КБ)

Этот вариант должен быть лучше :wink:

Это новая установка или вы переносите её на новый сервер?

Вам нужно посмотреть лог-файл и найти строку “migrate”, чтобы определить ошибку миграции.

Вот сама ошибка:

PG::DuplicateObject: ERROR:  type "hotlinked_media_status" уже существует

Это может быть связано с тем, что что-то было мигрировано, а затем коммит откатили. Это похоже на вашу ситуацию, но не является решением: Restore fails with "hotlinked_media_status" already exists. Возможно, это поможет: Upgrading 2.7 to 3.1 failing: "hotlinked_media_status" already exists - #5 by merefield

Также стоит исправить это, хотя сейчас это не наносит вреда:

Имя плагина — 'discourse-topic-voting', но имя директории плагина — 'discourse-voting'

Если вы будете делать это снова, пожалуйста, просто укажите ссылку на файл, не упаковывая его в tar-архив.