Поделиться: простой способ настроить страницу-заглушку во время обновления

Примечание: Не уверен, куда это лучше разместить, пожалуйста, переместите в более подходящее место, если я что-то упустил.

Хотел поделиться быстрым и немного кустарным способом, который я придумал на прошлой неделе, чтобы быстро развернуть страницу-заглушку во время обновления Discourse. Я прочитал все существующие руководства, но ничего не знаю об nginx, а схема с двумя контейнерами выглядела очень пугающе.

Коротко: я что-то сделал, код ниже. :backhand_index_pointing_down:

Node.js на помощь

Я подумал: какой самый быстрый способ запустить крошечный веб-сервер с одной страницей? Затем вспомнил, что 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>This page was last updated at: LASTUPDATE</p>

В файле server.js я заменяю LASTUPDATE на дату/время последнего обновления файла index.html. Это даёт людям представление о том, когда началось обновление, и я указываю на странице, что процесс займёт 10–15 минут.

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

Ой, нужен https :sweat_smile:

Время обновлять боевой сервер и показать людям мою новую быструю страницу-заглушку!

Но всё пошло не по плану. Боевой сайт находится за Cloudflare и требует наличия полных сертификатов сквозного шифрования, поэтому я вывел форум из строя на 15 минут, и пользователи видели только страницу ошибки Cloudflare :person_facepalming:

К счастью, ещё немного копирования/вставки из StackOverflow помогло. Я переключил сервер с http на https и получил файлы cert.key и cert.pem, чтобы убедиться, что цепочка сертификатов целая.

Следующее обновление прошло более успешно, и страницы-заглушки появились так, как задумано:

Просто покажите код!

Вот два файла, которые я использую для этой страницы-заглушки:

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 лайка