참고: 이 내용을 어디에 배치해야 할지 잘 모르겠습니다. 놓친 부분이 있다면 더 적절한 위치로 옮기셔도 됩니다.
Discourse 업그레이드를 수행할 때 빠른 임시 페이지를 띄우는 방법 중, 지난 한 주 동안 제가 고안해 낸 좀 엉성하지만 간편한 방식을 공유하고자 합니다. 기존 가이드를 모두 읽어 봤지만, nginx에 대해서는 전혀 알지 못했고 듀얼 컨테이너 설정은 꽤 intimidating하게 느껴졌습니다.
요약하자면, 제가 만든 것이 있습니다. 코드는 아래에 있습니다. ![]()
Node.js가 구원투수로 등장
저는 이렇게 생각했습니다: 단일 페이지로 초소형 웹 서버를 가장 빠르게 띄우는 방법은 무엇일까? 그리고 마침 node.js가 설치되어 있다는 것을 떠올렸습니다. node.js만으로도 되지 않을까요?
간단한 검색과 Stack Overflow에서 복사/붙여넣기를 한 후, 포트 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가 필요합니다 
이제 라이브 서버를 업그레이드하고 사람들에게 새로운 빠른 대기 페이지를 보여줄 차례입니다!
기대했던 대로 진행되지 않았습니다. 라이브 사이트는 Cloudflare 뒤에 있으며 완전한 엔드투엔드 인증서가 필요하므로, 포럼을 15분 동안 내렸고 Cloudflare 오류 페이지만 표시되었습니다 ![]()
다행히 Stack Overflow에서 더 많은 복사/붙여넣기가 도움이 되었습니다. 서버를 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
그리고 끝입니다. 누군가에게 도움이 되기를 바랍니다!
