Ха-ха, я рад, что вы спросили, потому что я не удосужился объяснить эту часть (мне следовало это сделать — здесь есть что рассказать, и Cloudflare довольно сложен!).
Когда настроен маршрут для Workers, каждая загрузка изображения и просмотр страницы на форуме проходят через этого Worker.
Таким образом, если у вас относительно загруженный форум, чтобы не исчерпать лимит бесплатного тарифа за один день, имеет смысл не держать этот маршрут включенным постоянно. Речь идет именно о маршруте Worker, а не о странице обслуживания — страницу обслуживания можно оставить включенной всё время; она не будет вызываться, пока не активирован маршрут Worker. Речь идет только о Шаге 2, где вы назначили маршрут (который легко настроить и удалить). Если вы не используете платный план Cloudflare, то хорошим тоном считается держать его включенным только во время проведения собственного обслуживания.
Перейдите на страницу маршрутов Workers для вашего домена в Cloudflare и нажмите кнопку справа от маршрута.
Не волнуйтесь, сам код Worker не будет удален, только правило маршрутизации. В следующий раз, когда вы будете выполнять пересборку или обновление, вы сможете просто добавить его снова, как в Шаге 2 выше.
Если вы используете платный план Cloudflare, то вам не о чем беспокоиться. Однако в этом случае вы можете использовать страницы ошибок Cloudflare вместо страницы Workers… (Я уже упоминал, что Cloudflare довольно сложен? ЛОЛ).
ниже приведена расширенная конфигурация для администраторов
Если вы хотите полностью автоматизировать обновления на бесплатном плане, вам следует использовать токен API Cloudflare, ваш zone-id и команду curl, чтобы получить route id (идентификатор маршрута) для Workers. Затем отредактируйте скрипт /root/update-web.sh, добавив туда немного «веселой» логики для автоматического включения и выключения маршрута Worker:
#!/bin/bash
cd /var/discourse
CF_TOKEN="your_actual_token_here" #<---Токен API Cloudflare
ZONE_ID="xxxx" #<---Взят со страницы профиля Cloudflare
ROUTE_ID="xxxx"
WORKER_NAME="my-site-maintenance-page"
echo "➡️ Загрузка последних скриптов Docker Discourse..."
git pull
echo "➡️ Инициализация нового веб-контейнера в фоновом режиме..."
./launcher bootstrap web_only
if [ $? -eq 0 ]; then
echo "✅ Инициализация успешна!"
# ВКЛЮЧАЕМ Worker для страницы обслуживания Cloudflare
echo "🚧 Включение страницы обслуживания..."
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/workers/routes/$ROUTE_ID" \
-H "Authorization: Bearer $CF_TOKEN" \
-H "Content-Type: application/json" \
--data '{"pattern":"*your-site.com/*","script":"'$WORKER_NAME'"}' > /dev/null
# Замена контейнеров (окно простоя 30 секунд)
echo "🔄 Замена контейнеров..."
./launcher destroy web_only && ./launcher start web_only
# ВЫКЛЮЧАЕМ Worker для страницы обслуживания Cloudflare
echo "🌍 Отключение страницы обслуживания..."
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/workers/routes/$ROUTE_ID" \
-H "Authorization: Bearer $CF_TOKEN" \
-H "Content-Type: application/json" \
--data '{"pattern":"*your-site.com/*","script":null}' > /dev/null
echo "🚀 Готово! Сайт обновлен без видимого простоя."
else
echo "❌ Инициализация не удалась! Прерываем замену, чтобы текущий сайт оставался в сети."
fi
Я использую предыдущую версию скрипта, потому что мне не хочется автоматизировать всё подряд, и мне нравится присутствовать при выполнении обновлений/пересборок. Я просто добавляю маршрут Workers прямо перед обновлением, а затем удаляю его после. Это занимает всего несколько секунд.
Мои общие шаги:
Добавить маршрут Workers в Cloudflare
Подключиться к Hetzner по SSH
Выполнить системные обновления (например: sudo apt update && sudo apt upgrade -y, затем перезагрузить сервер, если необходимо)
Я совершенно не разбираюсь в программировании и мире разработки, если не считать одного единственного эксперимента с «Hello World» на Visual Basic, который я когда-то давно проводил. Однако я могу кое-что сделать, потому что лучше разбираюсь в администрировании своих серверов WordPress и Mastodon/Pixelfed, а также, как-никак, своего Discourse. Плюс есть такая штука, как ИИ (которая, кстати, для новичка оказывается не такой простой, как это рекламируется).
Я не знаю, возможно ли это в принципе в Discourse из-за Docker, но в обычном мире Nginx-Varnish-WordPress я создал систему, при которой сервер Plesk получает информацию об ошибках 50x и показывает страницу ошибки. На самом деле у меня есть три варианта настройки: фронтенд-сервер Nginx показывает сгенерированный снимок контента, если Varnish недоступен; Varnish начинает использовать снимок для некэшированного контента, если бэкенд, связанный с WordPress, недоступен; и третий вариант — страница ошибки, если фронтенд-сервер Nginx не отвечает.
Решения с Varnish не подходят для Discourse, но я не вижу причин, по которым нельзя было бы построить подобную «паутину» и в мире Docker, где любая ошибка 50x приводила бы к отображению страницы ошибки.
Хотя такая система могла бы быть очень подвержена ошибкам. И я совершенно не представляю, что произойдет, если пользователей будет больше, чем горсть.
К тому же есть самый очевидный ответ, конечно: использовать, например, Nginx перед Discourse. Я использовал такой подход, прежде чем перешел на двухконтейнерную конфигурацию.
Наконец-то я нашёл время, чтобы снова установить Discourse. Подумав о том, где я сейчас нахожусь, и сколько обслуживания требуют два контейнера, я решил пока остаться с одним. Если в будущем мне понадобятся два контейнера, я пересмотрю всё, что было сказано здесь. Кроме установки плагинов, в которой, кажется, я буду нуждаться не так часто, как в управлении компонентами, то, что сообщество будет недоступно 20 минут в период, когда онлайн меньше людей, а также баннер, предупреждающий о дате и времени простоя, кажется вполне разумным решением на данный момент.
Поскольку процесс инициализации нового контейнера при сохранении работоспособности сайта значительно менее стрессовый: если сборка сломается, вам не нужно паниковать, и у вас будет достаточно времени, чтобы исправить ошибку, не отключая сайт от сети.
Хорошо, значит, вы рекомендуете использовать оба варианта, и именно поэтому это «меньше головной боли».
Так, как человек без опыта в этом вопросе, я полагаю, что наличие двух контейнеров не означает наличие двух экземпляров Discourse, верно?
Я читаю эту тему:
и этот пост:
чтобы понять, сколько это потребует усилий и внимания, чтобы в итоге не оказаться с чем-то, чем я не смогу управлять, и не сделать процесс более проблематичным, чем все те сложности, которые могут возникнуть при использовании всего одного контейнера.
Хочу похвалить за публикацию о настройке с двумя контейнерами. Я использовал один контейнер, и обычно это занимало 3–5 минут (на выделенном сервере с 64 ГБ ОЗУ).
Подскажите, пожалуйста, на простых и понятных примерах, когда нужно обновлять оба контейнера в двойной установке? Имею в виду, какие обновления Discourse требуют перезапуска обоих контейнеров, а какие — только недавно созданного web_container?
Часть с tee нужна только для логирования, так как просматривать её (мне) удобнее, чем поток в tmux, который я использую.
Но по сути это абсолютно то же самое, что использование app.yml и пересборка, только это гораздо меньше беспокоит пользователей. Конечно, есть и data-контейнер, но он требует внимания и заботы очень редко — а если вы будете выполнять более сложные манипуляции с контейнером, вы, скорее всего, и так знаете, что и когда делать с контейнерами.
Если обновление с двумя контейнерами завершится ошибкой, у вас всё равно будет рабочий и живой форум, тогда как при использовании одного контейнера он мог бы упасть.
Так что только запуск требует немного больше усилий, но инструкции довольно ясны. Я бы сказал, что использование mail-reveiver — более сложная задача, если вы используете Amazon SES.
Например, я не могу просто проигнорировать комментарий такого рода, поскольку, судя по всему, обновление/апгрейд перестаёт быть таким простым, как нажатие кнопки, и требует больше внимания и сосредоточенности. Для опытного человека это может показаться лёгким и очевидным, но для новичка — не обязательно:
Можно ли сказать, что инструкции в этой теме всё ещё актуальны в 2026 году, учитывая, что она была создана в 2015-м?
Мне не сложно попробовать, так как я только что снова установил Discourse. Если что-то пойдёт не так, я всегда смогу вернуться к одному контейнеру. Просто хочу убедиться, что, дойдя до середины процесса, я не начну выполнять действия, которые больше не актуальны в 2026 году…
Для меня экономия в несколько минут составляет более 20 минут. Утверждение о том, что это происходит раз в месяц, верно, если обновляться раз в месяц, но я обновляю систему как минимум дважды в неделю. А если какой-то плагин не сработал и приходится делать несколько попыток (ведь мы, конечно, работаем с боевыми инстансами ), то такой длительный простой просто невыносим.
Никаких подробностей в анонсах каждого нового релиза, которым нужно следовать, не существует. Возможно, у mcdanlj они есть, но он не обычный системный администратор, а работает на гораздо более высоком уровне.
А с другой, ваш ответ выше звучит так, будто работы будет больше, когда вы пишете:
Само по себе это звучит так, будто два контейнера действительно сложнее в обслуживании, а не так же, как один. Да, я понимаю всё насчёт простоя и так далее, но обслуживание самих контейнеров кажется более сложным и более подверженным ошибкам, чем простой апгрейд с одним контейнером. Или я что-то упускаю?
Вы упускаете из виду, что при использовании одного контейнера команда ./launcher rebuild app останавливает и веб-часть, и базу данных, обновляет обе, но база данных в этом крайне редко нуждается, а после завершения работы всё запускается заново только если не возникло никаких проблем.
В случае с двумя контейнерами вы пересобираете только “web”, а не контейнер с данными. Если всё прошло гладко, старый контейнер будет уничтожен и запущен новый. Если же что-то пойдёт не так, ваш старый и работоспособный “web” продолжит функционировать.
Таким образом, единственное реальное отличие заключается в том, как обрабатываются обновления программного обеспечения и пара других аспектов базы данных.
Конечно, вариант с одним контейнером тоже возможен. Но главная мысль в том, что при создании двух контейнеров единственное реальное отличие заключается в имени уровня сложности, которое используется при обновлении, — а для этого есть alias
Это было написано в старые времена, когда анонсы писались вручную и в них могло говориться о том, что пора обновить базу данных. Новый автоматизированный сайт выглядит эффектнее, но в нём нет человеческих заметок о том, что на самом деле важнее всего, как это было раньше.
Сегодня, я полагаю, нужно самому замечать посты о том, что база данных обновляется? Кажется, я пропустил их на протяжении нескольких месяцев.
Однако это происходит раз в несколько лет, и база пересоздаётся, когда вы явно пересобираете её, а CDCK, похоже, некоторое время сохранял совместимость со старыми версиями pgsql. Так что это никогда по-настоящему не доставляло мне хлопот. Пока что.
Я очень люблю настройку с двумя контейнерами (или даже больше!) для себя, но я всё же оговариваюсь, потому что это не самое простое решение для всех. Мне трудно судить, для кого развёртывание с двумя контейнерами будет ощущаться как «ну конечно, это же просто», а для кого — как «фу, я просто хочу нажать на кнопку».