共有:アップグレード中の簡易待機ページ設定方法

注意: どこに配置すればよいかわかりません。もし私が何か見落とした点があれば、より適切な場所に移動してください。

Discourse のアップグレードを行う際に、一時的なページを素早く表示するための、この一週間で考案した簡単なハック的な方法を共有したいと思います。既存のガイドはすべて読みましたが、nginx については何も知らず、デュアルコンテナの設定は非常に intimidating に見えました。

tl;dr; 作成しました。コードは以下にあります。:backhand_index_pointing_down:

Node.js が救世主に

そこで考えました。単一のページで非常に小さな Web サーバーを起動する最も簡単な方法は何だろうか? Node.js はすでにインストールされていることを思い出し、それだけを使ってもなんとかなるだろうか?

少し検索して Stackoverflow からコピー&ペーストしたところ、ポート 80 でリッスンする小さなものができました!

プロセスは非常に手動ですが、問題ないと思います。アップグレード実行中にログを監視する必要があるため、信号が表示されるのを待ちます。

Stopping old container
+ /usr/bin/docker stop -t 600 app

その時点で、別の SSH セッションを開き、次のように実行します。

touch index.html
node server.js 80

index.html ファイルを touch して、更新日時を読み取り、プレースホルダーを置き換えます。index.html にはこの行があります。

<p>このページは最後に更新された日時: LASTUPDATE</p>

server.js ファイルでは、その LASTUPDATEindex.html ファイルが最後に更新された日時で置き換えます。これにより、アップグレードがいつ開始されたかの目安となり、ページには 10〜15 分かかると記載しています。

これで、開発サーバーで簡単にテストを実行でき、本番環境でも実施できる準備が整いました。

おっと、https が必要です :sweat_smile:

本番サーバーをアップグレードして、新しい一時ページを皆に見せる時が来ました!

予想通りにはいきませんでした。本番サイトは Cloudflare の背後にあり、エンドツーエンドの証明書がすべて利用可能である必要があります。そのため、フォーラムを 15 分間停止させ、Cloudflare のエラーページしか表示されませんでした :person_facepalming:

幸いなことに、Stack Overflow からさらにコピー&ペーストして解決しました。サーバーを http から https に切り替え、cert.keycert.pem ファイルを取得して、証明書チェーンが完全であることを確認しました。

次のアップグレードはより大きな成功を収め、一時ページは設計どおりに表示されました。

コードを見せてください!

この一時ページに使用している 2 つのファイルは次のとおりです。

index.html

<!DOCTYPE html>
<html lang="en-US">
<head>
        <meta charset="utf-8">
        <title>We'll be right back</title>
</head>
<body>
        <h1>We'll be right back</h1>
        <p>Sorry for the temporary outage, we're currently applying an update, this usually take 10-15 minutes.</p>
        <p>This page was last updated at: LASTUPDATE</p>
</body>
</html>

server.js

var http = require("http"),
  https = require("https"),
  url = require("url"),
  path = require("path"),
  fs = require("fs"),
  port = process.argv[2] || 81;

const options = {
  key: fs.readFileSync("cert.key").toString(),
  cert: fs.readFileSync("cert.pem").toString(),
};

https
  .createServer(options, function (request, response) {
    var uri = url.parse(request.url).pathname,
      filename = path.join(process.cwd(), uri);

    fs.exists(filename, function (exists) {
      if (!exists) {
        response.writeHead(404, { "Content-Type": "text/plain" });
        response.write("404 Not Found\n");
        response.end();
        return;
      }

      let indexFile = (filename += "index.html");
      if (fs.statSync(filename).isDirectory()) indexFile;

      fs.readFile(filename, "utf8", function (err, file) {
        if (err) {
          response.writeHead(500, { "Content-Type": "text/plain" });
          response.write(err + "\n");
          response.end();
          return;
        }

        var stats = fs.statSync(indexFile);
        var mtime = stats.mtime;

        response.writeHead(200);
        file = file.replace(/LASTUPDATE/g, mtime);
        response.write(file, "utf8");
        response.end();
      });
    });
  })
  .listen(parseInt(port, 10));

console.log(
  "Static file server running at\n  => https://localhost:" +
    port +
    "/\nCTRL + C to shutdown"
);

上記のように、次のように実行できます。

touch index.html
node server.js 443

443 引数は実行したいポートです。デフォルトではポート 81 で実行されるため、実際にアップグレード中に実行する前に、curl で出力をテストできます。

curl -k https://localhost:81

Discourse のアップグレード中に、完了すると次のような表示が見られます。

Error starting userland proxy: listen tcp4 0.0.0.0:443: bind: address already in use.

その時点で Node サーバーを終了し、Discourse を再起動します。

./launcher restart app

これで完了です。誰かの役に立てば幸いです!

「いいね!」 3