Compartiendo: una forma básica de configurar una página de espera durante la actualización

Nota: no estoy seguro de dónde poner esto, siéntete libre de moverlo a un lugar más apropiado si me perdí algo.

Solo quería compartir una forma rápida y rudimentaria que he ideado en la última semana para poner una página rápida al hacer una actualización de Discourse. Leí todas las guías existentes, pero no sé nada de nginx y una configuración de doble contenedor me parecía muy intimidante.

tl;dr; Hice algo, el código está abajo. :backhand_index_pointing_down:

Node.js al rescate

Entonces pensé: ¿cuál es la forma más rápida de iniciar un servidor web súper pequeño con una sola página? Entonces recordé que node.js estaba instalado de todos modos, ¿podría tal vez arreglármelas solo usándolo?

Una búsqueda rápida y copiar/pegar de Stackoverflow después, ¡tenía una pequeña cosa escuchando en el puerto 80!

El proceso es súper manual, pero creo que está bien, necesito monitorear los registros cuando la actualización se esté ejecutando de todos modos, así que espero a ver la señal:

Deteniendo el contenedor antiguo
+ /usr/bin/docker stop -t 600 app

En ese momento, tendría otra sesión SSH abierta donde ejecuto rápidamente:

touch index.html
node server.js 80

Hago touch al archivo index.html para poder leer la fecha de actualización de él y reemplazar un marcador de posición. En mi index.html tengo esta línea:

<p>Esta página se actualizó por última vez a las: LASTUPDATE</p>

En el archivo server.js, reemplazo ese LASTUPDATE con la fecha/hora en que el archivo index.html se actualizó por última vez. Esto solo da a las personas una idea de cuándo comenzó la actualización y anoto en la página que tomará de 10 a 15 minutos completarse.

Esto me permitió ejecutar fácilmente algo en mi servidor de desarrollo como prueba y me sentí listo para hacerlo en producción.

Oops, necesitamos https :sweat_smile:

¡Es hora de actualizar el servidor en vivo y mostrarle a la gente mi nueva página de espera rápida!

Eso no salió como se esperaba. El sitio en vivo está detrás de Cloudflare y requiere que los certificados de extremo a extremo estén disponibles, así que desmantelé el foro durante 15 minutos y solo tuve una página de error de Cloudflare para mostrar :person_facepalming:

Afortunadamente, más copiar/pegar de Stack Overflow ayudó. Cambié el servidor de http a https y obtuve los archivos cert.key y cert.pem para asegurarme de que la cadena de certificados estuviera intacta.

La siguiente actualización fue un mayor éxito y las páginas de espera aparecieron como se diseñaron:

¡Solo muéstrame el código!

Aquí están los dos archivos que estoy usando para esta página de espera:

index.html

<!DOCTYPE html>
<html lang="en-US">
<head>
        <meta charset="utf-8">
        <title>Volveremos pronto</title>
</head>
<body>
        <h1>Volveremos pronto</h1>
        <p>Disculpe la interrupción temporal, actualmente estamos aplicando una actualización, esto generalmente toma de 10 a 15 minutos.</p>
        <p>Esta página se actualizó por última vez a las: 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(
  "Servidor de archivos estáticos ejecutándose en\n  => https://localhost:" +
    port +
    "/\nCTRL + C para apagar"
);

Como se mencionó anteriormente, puedes ejecutarlo de la siguiente manera:

touch index.html
node server.js 443

El argumento 443 es el puerto en el que deseas ejecutarlo, por defecto se ejecuta en el puerto 81 para que pueda hacer un curl para probar cuál será la salida, antes de hacerlo realmente durante la actualización:

curl -k https://localhost:81

En algún momento durante la actualización de Discourse, cuando se complete, verás:

Error al iniciar el proxy de userland: listen tcp4 0.0.0.0:443: bind: address already in use.

Es entonces cuando termino el servidor Node y reinicio Discourse:

./launcher restart app

Y eso es todo. ¡Espero que esto ayude a alguien!

3 Me gusta