メンテナンスページの回避策 - これって可能?

私のアップデートにエラーが発生しました

api_key = "a quick brown fox"
fetch("https://api.example.com/data", headers: { 'Authorization' => api_key })

修正にご協力ください。

やあ!

あなたの質問に答えているわけじゃないけど、ただ好奇心が湧いただけ。なぜメンテナンスページが必要だと思うの? 設置するのは結構めんどうくさいし、得られるメリットもほとんどないように思えるけど。

私のインスタンスは、アップデートのために月に5分ダウンするくらいで、それくらいが限界だよね。

プラグインのインストールなど、大きな変更を加えるたびに、それが完了するまで20分ほどかかることがありました。

このような作業は毎週、いや毎月行われるものではないので、大した問題ではありません。しかし、新規訪問者にとって、何かが正常に動作していないことを示す不格好なページは、良い第一印象を与えません。サイトがダウンしていることを知らないリピーターにとっても、コミュニティ全体が閉鎖されたのではないかと「パニックモード」に陥らせ、中にはすぐにメールを送って状況を確認しようとする人もいるかもしれません。

訪問者、新旧を問わず、現在何が起こっているのかを伝えるのは、ちょっとした気配りとして良いと思います。

Claudeが提案したこのアプローチが数分で完了し、その後すぐに修正が必要になるものではないなら、その時間は無駄にはならないでしょう。

2つのコンテナインストールに移行すれば、数秒で完了します。

必要であれば、あなたやメインのユーザーが眠っている夜間に切り替えをスケジュールすることもできます。

メンテナンスページは不要です。

dual container build を Cloudflare CDN の背後で運用しています。デュアルコンテナ構成はダウンタイムを最小限に抑え、私の 2 つのメインの本番フォーラムでは、再構築時に最大 30 秒のオフライン時間しか発生しません。メンテナンスページを表示させるのは気に入っています。デフォルトの Web サーバーの停止ページは見た目が悪く、どれくらいの時間オフラインになるのかを示す情報が全くないからです。

例えば、your-domain.com というドメインを持つサイトの場合、Cloudflare Workers のルートを *yourdomain.com/*(アスタリスクを含める)に設定するだけです。

ステップ 1: Worker ページの作成

Cloudflare の「Workers & Pages」設定ページでメンテナンスページを設定できます。「アプリケーションを作成」ボタンをクリックします:

次に、Hello World テンプレートを使用します:

名前を付けて「デプロイ」をクリックします:

次に、そのメンテナンスページの概要ページに移動し、「コードを編集」をクリックします:

そして、このコードを worker.js のコードウィンドウに貼り付けます(あなたのドメインと、表示したいメッセージ、テキスト、文字色、背景色などを編集してください):

export default {
  async fetch(request, env, ctx) {
    try {
      // サーバーから元のリクエストを取得
      const response = await fetch(request);

      // あなたのサイトがコンテナを切り替えている場合、502、521、または 530 エラーを返します
      if (response.status === 502 || response.status === 521 || response.status === 530) {
        return returnCustomErrorPage();
      }

      // 問題がない場合、通常のフォーラムトラフィックを返します
      return response;
    } catch (e) {
      // サーバーが完全に到達できない場合
      return returnCustomErrorPage();
    }
  }
};

function returnCustomErrorPage() {
  const html = `
    <!DOCTYPE html>
    <html lang="ja">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>システム更新中 - YOUR-SITE.com</title>
      <style>
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; text-align: center; padding: 50px; color: #333; background-color: #f9f9f9; }
        h1 { font-size: 2.5em; margin-bottom: 0.5em; color: #9400D3; }
        p { font-size: 1.2em; line-height: 1.5; }
        .container { max-width: 600px; margin: 0 auto; background: white; padding: 40px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
      </style>
    </head>
    <body>
      <div class="container">
        <h1>短時間のシステム更新中</h1>
        <p><strong>YOUR-SITE</strong> で約 30 秒のシステム更新を行っています。</p>
        <p>お飲み物を一口どうぞ。オンラインに戻り次第、このページは自動的にリフレッシュされます。</p>
      </div>
      <script>
        // 10 秒ごとにサイトが復旧したか自動的にチェック
        setInterval(function() {
          window.location.reload();
        }, 10000);
      </script>
    </body>
    </html>
  `;

  return new Response(html, {
    status: 503, // 503 は SEO に最適です。ダウンタイムで Google からペナルティを受けるのを防ぎます
    headers: {
      "Content-Type": "text/html;charset=UTF-8",
      "Retry-After": "30"
    }
  });
}

だいたいこのような見た目になります。保存するには「デプロイ」をクリックします:

ステップ 2: ルートの追加

次に、Cloudflare Workers のルートページに移動し、「ルートを追加」ボタンをクリックして新しいルートのモーダルを開きます。ドメインルートを記入し、先ほど作成した Worker ページを選択して、「保存」をクリックします:

ステップ 3: 更新や再構築の実行

これで、サーバーに SSH で接続してシステム更新を実行したり、再構築を行ったりした際、サイトダウンやエラーページではなく、実際にダウンタイムが発生した際にこのページが表示されます(私のサイトでは最大 30 秒としています)。

メンテナンス中は Workers ルートページを追加・削除する傾向がありますが、常時残しておく方もいます(私は実際のページのコードは残したまま、ルートの追加と削除のみを行っています)。

これでおしまいです。

オプション: スクリプトとスケジュールによる更新の実行

また、サーバー上で Unix シェルスクリプトを使用して、デュアルコンテナ固有の更新を実行しています。以下のように作成しました:

cat << 'EOF' > /root/update-web.sh
#!/bin/bash
cd /var/discourse
echo "➡️ Discourse Docker スクリプトの最新バージョンを取得中..."
git pull

echo "➡️ 背景で新しい Web コンテナをブートストラップ中(約 8 分かかる)..."
./launcher bootstrap web_only

if [ $? -eq 0 ]; then
    echo "✅ ブートストラップ成功!コンテナを切り替え中..."
    ./launcher destroy web_only && ./launcher start web_only
    echo "🚀 完了!ダウンタイムをほぼゼロに抑えてサイトを更新しました。"
else
    echo "❌ ブートストラップ失敗!現在のサイトをオンラインのまま保つため、切り替えを中止します。"
fi
EOF

chmod +x /root/update-web.sh

その後、サーバーの root プロンプトで ./update-web.sh コマンドを実行します。


:warning: 編集: 有料の Cloudflare アカウントをお持ちでない限り、以下の手順は実行しないでください。

cron ジョブを使用して、ローカル時間の日曜日午前 1 時など、特定の時間に自動化できます。私の場合、ローカル時間 1:00UTC 8:00 です(SSH で接続した状態でコマンドプロンプトで date と入力すると、サーバーの UTC 日付を確認できます)。

つまり:

サーバーのタスクスケジューラーを開くには、このコマンドを実行します:

crontab -e

(エディタの選択を求められた場合は、好みのエディタを選択してください。1 の nano が最も簡単です)

コメントの一番下に移動して、これを貼り付けます:

0 8 * * 0 /root/update-web.sh >> /var/log/discourse-update.log 2>&1

(これは、日曜日の朝、UTC 8 時 0 分に /root/update-web.sh ファイルを実行するという意味です)

次に、保存して終了します(nano を使用している場合):

  1. Ctrl + O で保存。
  2. Enter で確認。
  3. Ctrl + X で終了。

その後、日曜日の朝に起きると、cat /var/log/discourse-update.log を実行して、正常に実行されたか確認できます。cron タスクスケジューラーを使用する場合は、Worker ページのルートを残しておく必要があります。

これでおしまいです。質問があれば教えてください。笑。思っていたよりもずっと簡単ですよ。笑 :grin:

わあ!そのような詳細な手順の説明、本当に感謝しています!:raising_hands:

私はあなたの返信をメモに保存しましたので、すぐにDiscourseを再インストールする際に、再度参照します。インストールが完了したら、たとえ時間がかかっても、必ず結果をお知らせします。現在はいくつかのコーディング作業を完了させており、その後で再びDiscourseに集中します。

また、「Webサーバーがダウンしています」ページが醜く、経験のないユーザーにはそのメッセージがあまり意味を持たない点には同意します。カスタムメッセージを含むシンプルなメンテナンスページを設けることは、設定に多少の手間がかかる場合でも、常に好ましい選択肢です。

改めて、この情報を共有するために時間を割いてくださったことに、心から感謝申し上げます。他の人々もこの情報を有益だと感じると願っています :slight_smile:

ここに問題の核心があります。

これは単純な変更ではなく、心配し維持しなければならない追加のインフラが必要になりますし、私見では、数秒のダウンタイムに対してそれだけの価値はありません。

おっしゃることはわかりますが、それは単なる一例に過ぎません。本当に何か壊れてしまい、数秒以上かかって修復が必要な場合はどうなるのでしょうか?

また、プラグインのインストール後、あなた方は数秒のダウンタイムしか経験していないようですが、私は20分近くダウンタイムを経験しました。なぜそのような違いが生じるのでしょうか?

2つのコンテナ構成(両方の投稿でリンクされており、変更不可能な依存関係)では、./launcher bootstrap web_only を使用して新しいビルドをブートストラップします(この間、サイトは100%正常に動作します)。その後、すでに構築された新しいコンテナを単純に破壊し、すぐに起動します(これには数秒しかかかりません)。

ああ、わかりました。それはまだ2コンテナのセットアップに関する話ですね。完全に2コンテナのセットアップを構築するのは労力の割に得られないと言っているのかと誤解していました。あなたが言っている「労力の割に得られない」というのは、そのメンテナンスページの追加作業のことですよね?

個人的には、イエスです。

30〜60秒の間に新しいナビゲーションが表示されるウェブ閲覧者に対して二重の保険(belt and braces)を設けたい場合は、メンテナンスページを表示することは妥当です。

ただし、その利点と、それを支えるインフラを維持するために必要な時間を比較衡量する必要があります。

なるほど、わかりました。ありがとうございます。

では、ここで質問です。2つのコンテナがある場合、それでも20分程度かかるのは変わりませんが、唯一の違いは、稼働していない方のコンテナで処理を実行させておき、準備が整ったら切り替えることができるという点です。この理解で合っていますか?

はい、コンテナのビルドにはまだ少し時間がかかります。なお、コミュニティへの通常サービスを提供しながら並行してこのプロセスを実行するには、サーバーが十分に強力である必要があります(最も重要なのは、まず十分なメモリを確保することです。したがって、SWAP領域が十分にあることを確認することが非常に重要です)。ビルド処理では少なくとも1つのCPUコアが専有されるため、サーバーには1~2つ多いコア数を持つことを検討してください。

今、すべてが理解できました。ありがとうございます。

最初はこれを使っていたのですが、もう利用できないようです:

なので、今後はこれを使う必要があります:

ちょっと価格が跳ね上がってしまいますね… :confused: しかも、サーバーのパフォーマンスは劣っているように見えます…?

この種のセットアップには、少なくとも4GBのメモリと3コア(“vcpu”)を推奨します…

別のトピックで質問されていたため、参考までに(編集:誤った)回答を記載します:Any cheaper alternatives to Hetzner? - #2 by Canapin

これがそれに合致する唯一のものですが… 価格の差がすごい…

image

仕方なく、まずは1つのコンテナで構築して、資金(:money_bag:)が揃ったらアップグレードすることにします。

情報をありがとう、ロバート!

私はそれに反対で、メンテナンスページを設ける価値があると思います。私の経験では、人々が Discourse のエラーページを最初にみたとき、まずリフレッシュボタンを押します。そうすると、コンテナの切り替えが完了すると自動的にサイトを再読み込みする、わずかな時間のメンテナンスページが表示されます。設定するのはそれほど手間ではなく、一度設定すれば済みます。デュアルコンテナ構成での再構築中、ブートストラップ部分はバックグラウンドで実行され、ユーザーはサイトを继续使用できます。一時的なダウンタイムを引き起こすのはコンテナの切り替え部分です(標準のシングルコンテナ構成とは異なります)。

サーバーのコストと選択は全く別の問題であり、別のトピックで議論されるべきです。

今はちょうど中間地点にいるような気がします。@merefield の方も含め、お二人の言いたいことはよくわかります。そんな機能があるのは素敵なアイデアですし、一度設定すればあとは放置で済むなら、それほど大したことではないのかもしれませんね?

一方で、最悪の場合に60秒もかかるのであれば、誰もがちょうど0秒のタイミングでサイトにアクセスして60秒待つわけではありません。5秒、20秒、60秒……人によって見せられる「未完成なページ」の時間は異なります。また、返信を読みながらいたり、書きながらいたりする間にはその切り替えが起きるため、そもそもそのページを見ない人もいるでしょう(そう思います?)。例えば、SENDボタンを押す前や、トピックの読み終わってREPLYを押す前、あるいは他のページに遷移する前に切り替えが完了している場合です。

nginxのルーティングに関する私の懸念は、単一コンテナ構成における20分という時間に関連していました。2コンテナ構成のオプションがあり、20分から最大でも60秒程度に短縮できるなら、本当にそれが重要な問題なのか疑問です。特に、トラフィックの少ない時間帯に、数秒間サービスが停止することをトップに告知できるなら、大きな問題にはならないでしょう?

じっくり考えてみる必要があります。もし良いサーバープランが見つかったら、2コンテナ構成は確実に導入するつもりです。

私のような初心者にもわかるように、これを明確に説明していただけますか? ワーカーについてはまだ慣れていません…

放置しておいても問題がないなら、なぜワーカーのルートページを追加したり削除したりするのですか? つまり、メンテナンスページを追加する場合、一度設定すれば、それ以降はCloudflareにアクセスする必要なく、単一コンテナの場合と同様に、常にTerminal経由でSSH接続してサーバー上ですべての操作を行うことができるのでしょうか?

@merefield は、これ(メンテナンスページ、ワーカーなど)もメンテナンスが必要なものだと指摘していました。そのため、これは「設定して忘れる」タイプのものなのか、それとも時々何かを行う必要があるのか疑問に思っています。