Node.js 애플리케이션을 Rocky Linux 9에 프로덕션 환경으로 설정하는 방법

Node.js는 서버 측 및 네트워킹 애플리케이션을 구축하기 위한 오픈 소스 JavaScript 런타임 환경입니다. 이 플랫폼은 Linux, macOS, FreeBSD 및 Windows에서 실행됩니다. Node.js 애플리케이션을 명령 줄에서 실행할 수 있지만, 이 자습서에서는 서비스로 실행하는 데 초점을 맞출 것입니다. 이는 부팅이나 실패 시에 재시작되며 프로덕션 환경에서 사용할 수 있습니다.

이 자습서에서는 단일 Rocky Linux 9 서버에서 프로덕션에 준비된 Node.js 환경을 설정합니다. 이 서버는 PM2에 의해 관리되는 Node.js 애플리케이션을 실행하고 Nginx 역방향 프록시를 통해 애플리케이션에 안전한 액세스를 제공합니다. Nginx 서버는 Let’s Encrypt가 제공하는 무료 인증서를 사용하여 HTTPS를 제공할 것입니다.

전제 조건

이 안내서는 다음을 가정합니다:

필수 작업을 완료하면 서버가 https://example.com/에서 도메인의 기본 플레이스홀더 페이지를 제공합니다.

단계 1 — Node.js 애플리케이션 생성

Hello World 애플리케이션을 작성해 보겠습니다. 이 예제 애플리케이션은 HTTP 요청에 “Hello World”를 반환합니다. 이 샘플 애플리케이션을 사용하여 Node.js를 시작하고 실행하는 데 도움이 됩니다. 자체 애플리케이션으로 바꿀 수 있습니다. 단지 애플리케이션이 적절한 IP 주소 및 포트에서 수신 대기하도록 수정하십시오.

Rocky Linux 9에 기본으로 제공되는 텍스트 편집기는 vi입니다. vi는 매우 강력한 텍스트 편집기이지만 사용 경험이 부족한 사용자에게는 다소 어려울 수 있습니다. Rocky Linux 9 서버의 구성 파일을 편집하는 데 더 사용자 친화적인 편집기인 nano와 같은 편집기를 설치하면 도움이 될 수 있습니다.

  1. sudo dnf install nano

이제 nano 또는 선호하는 텍스트 편집기를 사용하여 hello.js라는 샘플 애플리케이션을 만들어 보세요:

  1. nano hello.js

다음 코드를 파일에 삽입하세요:

~/hello.js
const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

파일을 저장하고 편집기를 종료하세요. nano를 사용하는 경우 Ctrl+X를 누르고, 나오라고 하면 Y를 입력한 후 Enter 키를 누르세요.

이 Node.js 애플리케이션은 지정된 주소(localhost)와 포트(3000)에서 대기하며, 200 HTTP 성공 코드로 “Hello World!”를 반환합니다. localhost에서 대기하고 있기 때문에 원격 클라이언트는 애플리케이션에 연결할 수 없습니다.

애플리케이션을 테스트하려면 다음을 입력하세요:

  1. node hello.js

다음과 같은 출력이 표시됩니다:

Output
Server running at http://localhost:3000/

참고: 이 방법으로 Node.js 애플리케이션을 실행하면 애플리케이션이 CTRL+C를 눌러 종료될 때까지 추가 명령을 차단합니다.

애플리케이션을 테스트하려면 서버에서 다른 터미널 세션을 열고 curl을 사용하여 localhost에 연결하세요:

  1. curl http://localhost:3000

다음 출력이 표시되면 애플리케이션이 올바르게 작동하고 올바른 주소와 포트에서 대기 중입니다:

Output
Hello World!

예상한 출력이 표시되지 않으면 Node.js 애플리케이션이 실행되고 올바른 주소와 포트에서 대기하도록 구성되어 있는지 확인하세요.

작동하는 것을 확인한 후 (아직 종료하지 않은 경우) CTRL+C를 눌러 애플리케이션을 종료하세요.

단계 2 — PM2 설치

이제 PM2를 설치해 보겠습니다. PM2는 Node.js 애플리케이션의 프로세스 관리자로, 애플리케이션을 백그라운드에서 서비스로 실행할 수 있게 해줍니다.

서버에 PM2의 최신 버전을 설치하려면 npm을 사용하십시오:

  1. sudo npm install pm2@latest -g

-g 옵션은 npm이 모듈을 전역적으로 설치하도록 지시하여 시스템 전역에서 사용할 수 있게 합니다.

먼저 백그라운드에서 응용 프로그램인 hello.js를 실행하는 pm2 start 명령을 사용해 보겠습니다:

  1. pm2 start hello.js

이렇게 하면 응용 프로그램이 PM2의 프로세스 목록에 추가되며, 각 응용 프로그램을 시작할 때마다 출력됩니다:

Output
... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

위에서 언급한대로 PM2는 파일 이름에서 .js 확장자를 제외한 것을 기반으로 자동으로 App name을 할당하고 PM2 id를 지정합니다. PM2는 또한 프로세스의 PID 및 현재 상태, 메모리 사용량 등 다른 정보를 유지 관리합니다.

PM2에서 실행 중인 애플리케이션은 애플리케이션이 충돌하거나 종료되면 자동으로 다시 시작됩니다. 그러나 startup 하위 명령을 사용하여 시스템 부팅 시 애플리케이션을 시작하도록 추가 단계를 수행할 수 있습니다. 이 하위 명령은 PM2와 그 관리 프로세스를 서버 부팅 시 시작하는 시작 스크립트를 생성하고 구성합니다:

  1. pm2 startup systemd
Output
… [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

제공된 명령을 복사하여 실행하십시오 (이는 Node.js 도구를 sudo로 실행할 때 권한 문제를 피하기 위함입니다).

  1. sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
Output
… [ 'systemctl enable pm2-sammy' ] [PM2] Writing init configuration in /etc/systemd/system/pm2-sammy.service [PM2] Making script booting at startup... [PM2] [-] Executing: systemctl enable pm2-sammy... Created symlink /etc/systemd/system/multi-user.target.wants/pm2-sammy.service → /etc/systemd/system/pm2-sammy.service. [PM2] [v] Command successfully executed. +---------------------------------------+ [PM2] Freeze a process list on reboot via: $ pm2 save [PM2] Remove init script via: $ pm2 unstartup systemd

지금은 방금 생성된 시스템 서비스를 Rocky Linux의 SELinux 보안 시스템과 호환되도록 편집해야 합니다. nano 또는 선호하는 텍스트 편집기를 사용하여 /etc/systemd/system/pm2-sammy.service 파일을 엽니다:

  1. sudo nano /etc/systemd/system/pm2-sammy.service

구성 파일의 [Service] 블록에서 PIDFile 설정의 내용을 아래 강조된 대로 /run/pm2.pid로 대체하고 다른 강조된 Environment 라인을 추가합니다:

/etc/systemd/system/pm2-sammy.service
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=sammy
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/home/sammy/.local/bin:/home/sammy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/sammy/.pm2
PIDFile=/run/pm2.pid
Restart=on-failure
Environment=PM2_PID_FILE_PATH=/run/pm2.pid

ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill

[Install]

파일을 저장하고 닫습니다. 이제 부팅 시 사용자에 대해 pm2를 실행하는 systemd unit을 만들었습니다. 이 pm2 인스턴스는 다시 hello.js를 실행합니다.

systemctl로 서비스를 시작하세요:

  1. sudo systemctl start pm2-sammy

systemd unit의 상태를 확인하세요:

  1. systemctl status pm2-sammy

systemd에 대한 자세한 개요는 Systemd Essentials: Working with Services, Units, and the Journal를 참조하세요.

우리가 다룬 내용 외에도 PM2는 응용 프로그램을 관리하거나 정보를 조회할 수 있는 많은 하위 명령을 제공합니다.

이 명령을 사용하여 응용 프로그램을 중지하세요 (PM2 App name 또는 id 지정):

  1. pm2 stop app_name_or_id

응용 프로그램을 다시 시작하세요:

  1. pm2 restart app_name_or_id

현재 PM2에서 관리하는 응용 프로그램 목록을 나열하세요:

  1. pm2 list

특정 응용 프로그램에 대한 정보를 가져오려면 App name을 사용하세요:

  1. pm2 info app_name

PM2 프로세스 모니터는 monit 하위 명령어로 끌어올릴 수 있습니다. 이는 응용 프로그램 상태, CPU 및 메모리 사용량을 표시합니다.

  1. pm2 monit

인수 없이 pm2를 실행하면 도움말 페이지와 예제 사용법이 표시됩니다.

Step 3 — 엔진엑스를 역방향 프록시 서버로 설정하기

응용 프로그램이 실행되고 localhost에서 수신 대기 중이지만 사용자가 액세스할 수 있는 방법을 설정해야 합니다. 이를 위해 엔진엑스 웹 서버를 역방향 프록시로 설정하겠습니다.

사전 필수 자습서에서 엔진엑스 구성을 /etc/nginx/conf.d/your_domain.conf 파일에 설정했습니다. 이 파일을 편집하십시오:

  1. sudo nano /etc/nginx/conf.d/your_domain.conf

server 블록 내에 기존 location / 블록이 있어야 합니다. 해당 블록의 내용을 다음 구성으로 대체하십시오. 응용 프로그램이 다른 포트에서 수신 대기하도록 설정된 경우 강조된 부분을 올바른 포트 번호로 업데이트하십시오:

/etc/nginx/conf.d/your_domain.conf
server {
...
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

이 설정은 서버를 루트에 대한 요청에 응답하도록 구성합니다. 서버가 your_domain에서 사용 가능한 경우, 웹 브라우저를 통해 https://your_domain/에 액세스하면 localhost의 포트 3000에서 수신 대기하는 hello.js에 요청이 전송됩니다.

동일한 서버 블록에 추가적인 location 블록을 추가하여 동일한 서버에 있는 다른 응용 프로그램에 액세스할 수 있습니다. 예를 들어, 다른 Node.js 응용 프로그램을 포트 3001에서 실행 중인 경우 다음 위치 블록을 추가하여 https://your_domain/app2를 통해 해당 응용 프로그램에 액세스할 수 있습니다:

/etc/nginx/conf.d/your_domain.conf — Optional
server {
...
    location /app2 {
        proxy_pass http://localhost:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

응용 프로그램의 위치 블록을 추가한 후 파일을 저장하고 편집기를 종료합니다.

다음을 입력하여 구문 오류를 도입하지 않았는지 확인합니다:

  1. sudo nginx -t

Nginx를 다시 시작합니다:

  1. sudo systemctl restart nginx

Node.js 응용 프로그램이 실행되고 응용 프로그램 및 Nginx 구성이 올바른 경우 이제 Nginx 역방향 프록시를 통해 응용 프로그램에 액세스할 수 있어야 합니다. 서버의 URL(공개 IP 주소 또는 도메인 이름)에 액세스하여 확인해보세요.

결론

축하합니다! 이제 Rocky Linux 9 서버에서 Nginx 역방향 프록시 뒤에서 Node.js 응용 프로그램이 실행 중입니다. 이 역방향 프록시 설정은 공유하려는 다른 응용 프로그램 또는 정적 웹 콘텐츠에 사용자 액세스를 제공할 수 있는 유연성이 있습니다.

다음으로, Docker로 Node.js 애플리케이션을 빌드하는 방법을 살펴볼 수 있습니다.

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-rocky-linux-9