Устранение сбоев при запуске в Discourse

Я все еще испытываю трудности с новым процессом «предварительной упаковки» (pre-bundling). Запуск (bootstrap) не удается на моем тестовом экземпляре, и я не понимаю почему. Отмечу, что это настройка с внешней базой данных PostgreSQL. Контейнеры работают за haproxy, который выступает в качестве ускорителя SSL. Здесь я запускаю запуск только для контейнера web_only. Текущая версия сборки (перед запуском) — 3.5.0.beta8-dev, Commits · discourse/discourse · GitHub

Вот текущий файл yml, вызывающий ошибку:

# ВАЖНО: УСТАНОВИТЕ СЕКРЕТНЫЙ ПАРОЛЬ в Postgres для пользователя Discourse
# TODO: измените SOME_SECRET в этом шаблоне

templates:
  - "templates/web.template.yml"
  ## Раскомментируйте следующую строку, чтобы включить прослушивание IPv6
  #- "templates/web.ipv6.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.socketed.template.yml"
  ## Раскомментируйте эти две строки, если хотите добавить Lets Encrypt (https)
  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

## Какие TCP/IP-порты должен открывать этот контейнер?
## Если вы хотите, чтобы Discourse использовал порт совместно с другим веб-сервером, например Apache или nginx,
## см. https://meta.discourse.org/t/17247 для деталей
expose:
  - "80:80"   # http
  - "443:443" # https

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

# любые дополнительные аргументы для Docker?
# docker_args:

params:
  ## Какую ревизию Git должен использовать этот контейнер? (по умолчанию: tests-passed)
  #version: tests-passed

env:
  LC_ALL: en_US.UTF-8
  LANG: en_US.UTF-8
  LANGUAGE: en_US.UTF-8
  DISCOURSE_DEFAULT_LOCALE: de

  ## Сколько одновременных веб-запросов поддерживается? Зависит от памяти и ядер CPU.
  ## будет установлено автоматически при запуске на основе обнаруженных CPU, или вы можете переопределить
  UNICORN_WORKERS: 4

  ## TODO: Доменное имя, на которое будет отвечать этот экземпляр Discourse
  DISCOURSE_HOSTNAME: 'forum2.netzwissen.de'

  ## Раскомментируйте, если хотите, чтобы контейнер запускался с тем же
  ## именем хоста (-h опция), что указано выше (по умолчанию "$hostname-$config")
  #DOCKER_USE_HOSTNAME: true

  ## TODO: Список email-адресов через запятую, которые станут администраторами и разработчиками
  ## при первой регистрации, например 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'admin@netzwissen.de'

  ## TODO: SMTP-сервер, используемый для проверки новых аккаунтов и отправки уведомлений
  # SMTP ADDRESS, username, и password обязательны
  # ВНИМАНИЕ: символ '#' в пароле SMTP может вызвать проблемы!
  DISCOURSE_SMTP_ADDRESS: mail.netzwissen.de
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: discourse@netzwissen.de
  DISCOURSE_SMTP_PASSWORD: [xxxxxxxxxxxxxxxxx}
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (опционально, по умолчанию true)
  #DISCOURSE_SMTP_DOMAIN: discourse.example.com    # (требуется некоторыми провайдерами)
  DISCOURSE_NOTIFICATION_EMAIL: discourse@netzwissen.de    # (адрес для отправки уведомлений)

  ## Если вы добавили шаблон Lets Encrypt, раскомментируйте ниже, чтобы получить бесплатный SSL-сертификат
  #LETSENCRYPT_ACCOUNT_EMAIL: me@example.com

## настройка подключения к базам данных
  DISCOURSE_DB_SOCKET: ''
  DISCOURSE_DB_USERNAME: [xxxxxxxxxxx]
  DISCOURSE_DB_NAME: [xxxxxxxxxxxxxxx]
  DISCOURSE_DB_HOST: [xxxxxxxxxxxxxxx]
  DISCOURSE_DB_PASSWORD: [xxxxxxxxxxxxxxx]
  ## кэширование redis на соседнем контейнере
  DISCOURSE_REDIS_HOST: redis

  ## Адрес http или https CDN для этого экземпляра Discourse (настроен на получение)
  ## см. https://meta.discourse.org/t/14857 для деталей
  #DISCOURSE_CDN_URL: https://discourse-cdn.example.com

## Максимальный ID учетной записи Maxmind и лицензионный ключ для поиска IP-адресов
## см. https://meta.discourse.org/t/-/173941 для деталей
  #DISCOURSE_MAXMIND_ACCOUNT_ID: 123456
  #DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456

volumes:
  - volume:
      host: /mnt/data/discourse/shared/web-only
      guest: /shared
  - volume:
      host: /mnt/data/discourse/shared/web-only/log/var-log
      guest: /var/log

## Плагины размещаются здесь
## см. https://meta.discourse.org/t/19157 для деталей
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-shared-edits.git
# некоторые плагины удалены, так как теперь они включены в ядро
# https://meta.discourse.org/t/bundling-more-popular-plugins-with-discourse-core/373574
## = теперь включены
##          - git clone https://github.com/discourse/discourse-chat-integration.git
##          - git clone https://github.com/discourse/discourse-openid-connect.git
##          - git clone https://github.com/discourse/discourse-calendar.git
##          - git clone https://github.com/angusmcleod/discourse-events.git
##          - git clone https://github.com/discourse/discourse-data-explorer.git
##          - git clone https://github.com/discourse/discourse-reactions.git
##          - git clone https://github.com/discourse/discourse-chat.git
##          - git clone https://github.com/discourse/discourse-ai.git
##          - git clone https://github.com/discourse/discourse-topic-voting.git
##          - git clone https://github.com/discourse/discourse-post-voting.git
##          - git clone https://github.com/discourse/discourse-user-notes.git
##          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/discourse/discourse-docs-card-filter.git
          - git clone https://github.com/discourse/discourse-doc-categories.git
##          - git clone https://github.com/discourse/discourse-assign.git
##          - git clone https://github.com/discourse/discourse-templates.git
          - git clone https://github.com/discourse/discourse-saved-searches.git
          - git clone https://github.com/discourse/discourse-tooltips.git
          - git clone https://github.com/discourse/discourse-category-experts.git
          - git clone https://github.com/discourse/discourse-activity-pub.git
          - git clone https://github.com/discourse/discourse-follow.git
          - git clone https://github.com/nathan-nz/discourse-wikified-posts.git
          - git clone https://github.com/discourse/discourse-whos-online.git
          - git clone https://github.com/merefield/discourse-workflow.git

## Помните, это синтаксис YAML — у вас может быть только один блок с именем
run:
  - exec: echo "Начало пользовательских команд"

  ## Если вы хотите настроить вход по паролю для root, раскомментируйте и измените:
  ## Используйте только одну из следующих строк:
  #- exec: /usr/sbin/usermod -p 'PASSWORD_HASH' root
  - exec: /usr/sbin/usermod -p "$(mkpasswd -m sha-256 'xxxxxxxxxxxxxxx')" root

## для работы за балансировщиком нагрузки haproxy с локальным nginx на хосте контейнера
  - replace:
      filename: /etc/nginx/conf.d/discourse.conf
      from: "types {"
      to: |
        set_real_ip_from 127.0.0.1/24;
        set_real_ip_from 10.0.0.0/24;
        real_ip_header X-Forwarded-For;
        real_ip_recursive on;
        proxy_set_header Host $http_host;
        proxy_set_header X-Request-Start "t=${msec}";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https; # заменено $thescheme;
        proxy_set_header X-Real-IP $remote_addr;
        types {

  ## Если вы хотите авторизовать дополнительных пользователей, раскомментируйте и измените:
  #- exec: ssh-import-id username
  #- exec: ssh-import-id anotherusername

  - exec: echo "Конец пользовательских команд"
  - exec: awk -F\# '{print $1;}' ~/.ssh/authorized_keys | awk 'BEGIN { print "Авторизованные SSH-ключи для этого контейнера:"; } NF\u003e=2 {print $NF;}'

Даже когда я добавляю блок rm -rf в файл yml:

- rm -rf discourse-chat-integration  
- rm -rf discourse-openid-connect         
- rm -rf discourse-calendar         
- rm -rf discourse-events         
- rm -rf discourse-data-explorer         
- rm -rf discourse-reactions         
- rm -rf discourse-chat         
- rm -rf discourse-ai         
- rm -rf discourse-topic-voting         
- rm -rf discourse-post-voting         
- rm -rf discourse-user-notes         
- rm -rf discourse-solved         
- rm -rf discourse-assign         
- rm -rf discourse-templates

Запуск все равно не удается с ошибкой:

/usr/local/lib/ruby/gems/3.3.0/gems/pups-1.3.0/lib/pups.rb
/usr/local/bin/pups --stdin

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

Я интерпретирую это как ошибку при миграции базы данных на этапе bundle exec rake db:migrate. Но в чем коренная причина? База данных discourse2 уже имеет расширение vector, которое требовалось для плагина discourse-ai (ранее уже установленного):

postgres=# \c discourse2  
psql (15.12 (Ubuntu 15.12-1.pgdg22.04+1), server 13.20 (Ubuntu 13.20-1.pgdg22.04+1))  
You are now connected to database "discourse2" as user "postgres".  
discourse2=# \dx  
                                   List of installed extensions  
  Name   | Version |   Schema   |                            Description                               
----------+---------+------------+-------------------------------------------------------------------  
hstore   | 1.7     | public     | data type for storing sets of (key, value) pairs  
pg_trgm  | 1.5     | public     | text similarity measurement and index searching based on trigrams  
plpgsql  | 1.0     | pg_catalog | PL/pgSQL procedural language  
unaccent | 1.1     | public     | text search dictionary that removes accents  
vector   | 0.8.0   | public     | vector data type and ivfflat and hnsw access methods  
(5 rows)

Позже я также вижу подсказки о плагинах, хотя строки git clone в файле yml все закомментированы:

---
HINT: The plugin 'discourse-openid-connect' is now bundled with Discourse and should not be included in your container configuration.
Remove the line 'git clone https://github.com/discourse/discourse-openid-connect' from your containers/web_only.yml file, then try again.
For more information, see https://meta.discourse.org/t/373574
---

Честно говоря, я немного запутался ::sleepy_face:

Что возвращает команда free -h?

root@docker3a:/var/discourse/containers# free -h
всего использовано свободно общ. Буфер/Кэш доступно
Память: 3,8Gi 2,0Gi 1,1Gi 3,8Mi 969Mi 1,8Gi

вероятно, 4 ГБ подкачки

Извините, моя ошибка, вывод был обрезан

root@docker3a:~# free -h
всего использовано свободно совместно Буфер/Кэш доступно
Память: 3,8Gi 2,0Gi 1,1Gi 3,8Mi 971Mi 1,8Gi
Подкачка: 974Mi 0B 974Mi

У виртуальной машины уже есть 4 ГБ оперативной памяти. Я добавил ещё 2 ГБ и запустил другой ./launcher rebuild web_only^, но ошибка осталась той же. Поэтому я сомневаюсь, что проблема связана с нехваткой места при сборке…

Что ж, мне требовался файл подкачки объёмом 2 ГБ при 8 ГБ оперативной памяти.

Я попробовал снова с 8 ГБ ОЗУ, но получил тот же результат ошибки. Обратите внимание, что это виртуальная машина на базе ядра (KVM) на хосте Proxmox (Features - Proxmox Virtual Environment).

Гость QEMU/KVM запрашивает память у хоста по мере необходимости гостевой ОС, но не возвращает память хосту автоматически, если гостевая ОС больше в ней не нуждается. Если хосту требуется память, ядро запросит у процессов возврат неиспользуемой оперативной памяти, поэтому QEMU попытается освободить часть памяти, но это зависит от гостевой ОС, которая должна сначала её освободить.

У меня никогда не было проблем с памятью при конфигурации 4 ГБ ОЗУ и 4 процессора, даже с плагином discourse-ai. Проблемы с загрузкой (bootstrap) появились только после этого объявления о связывании (bundling)…

Подождите, есть ли плагин discourse-openid-connect в вашем файле yml?

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

Подождите, плагин discourse-openid-connect есть в вашем YAML-файле?

Это проблема при миграции. Не могли бы вы прокрутить вверх и найти, что не удалось мигрировать?

До сих пор в моем списке плагинов был discourse-openid-connect. Я удалил его для «сборки после объединения» (post-bundling build). Теперь в YAML-файле сборки остались только эти плагины:

## non-bundled plugins
- git clone https://github.com/discourse/docker_manager.git\`

  • git clone https://github.com/discourse/discourse-shared-edits.git
  • git clone https://github.com/discourse/discourse-docs-card-filter.git
  • git clone https://github.com/discourse/discourse-doc-categories.git
  • git clone https://github.com/discourse/discourse-saved-searches.git
  • git clone https://github.com/discourse/discourse-tooltips.git
  • git clone https://github.com/discourse/discourse-category-experts.git
  • git clone https://github.com/discourse/discourse-activity-pub.git
  • git clone https://github.com/discourse/discourse-follow.git
  • git clone ``https://github.com/nathan-nz/discourse-wikified-posts.git
  • git clone https://github.com/discourse/discourse-whos-online.git
  • git clone ``https://github.com/merefield/discourse-workflow.git\`

Сборка, похоже, падает на этапе «bundle exec rake db:migrate». Но несколькими строками выше я вижу ошибку:

Gem::LoadError: can't activate multipart-post-2.4.0, already activated multipart-post-2.4.1 (Gem::LoadError)

discourse-wikified-posts уже находится в последней совместимой версии discourse-workflow уже находится в последней совместимой версии docker_manager уже находится в последней совместимой версии I,
[2025-07-28T06:34:13.916393 #1] INFO -- : > cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate' rake aborted! Gem::LoadError: can't activate multipart-post-2.4.0, already activated multipart-post-2.4.1 (Gem::LoadError) /var/www/discourse/lib/plugin_gem.rb:25:in `load' /var/www/discourse/lib/plugin/instance.rb:861:in `gem' […]

Я не разбираюсь в Ruby, но, возможно, это конфликт пакетов между multipart-post-2.4.0 и multipart-post-2.4.1?

Спасибо!
Thommie

Это так, и из-за этого у меня упали две сборки. По крайней мере, один из плагинов CDCK использовал старую версию multipart-post, которая, возможно, теперь обновлена.

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

Очень раздражает, и мне совсем не нравится это изменение.

Вам придется удалить workflow, пока я снова не обновлю зависимость.

Это система работает как задумано.

Когда мы управляем зависимостями gems с помощью Gemfile и Gemfile.lock, dependbot сканирует обновления, а мы поддерживаем актуальность с помощью наших внутренних процессов.

Как разработчик плагинов, вы теперь можете полагаться на зависимости gems, которые мы поставляем в ядре.

Это означает, что вам следует удалить multipart-post из файла plugin.rb вашего плагина и просто подключить его там, где вы его используете.

Один пункт меньше, о котором должны беспокоиться авторы плагинов.

Полезный отзыв, спасибо.

@Thomas_Rother Я убрал зависимость (и ещё одну) из плагина, попробуй собрать снова.

@merefield @sam :smiley: — успех!! С коммитом 6be7a44 в плагине Роберта GitHub - merefield/discourse-workflow: A workflow system for Topics that implements a configurable multi-stage process · GitHub сборка прошла успешно. Спасибо за анализ и исправление!