[PM2] PM2 동작하지 않는 문제(3000포트 리슨 안됨) 해결
문제
운영 서버에서 PM2를 실행하는데 .env.local 파일을 읽는다.
확인해보니 포트 3000에서 LISTEN하지 않고 있었다. 그래서 npm run start를 수동으로 실행해야만 API가 정상적으로 작동하는 문제가 발생했다.
pm2 설정이 필요한 분들은 아래 글을 참고해주세요!
2024.08.26 - [💡/오류노트] - [Caddy] 3000포트가 열리지 않는 문제 해결(+PM2)
원인
PM2에 환경 변수 설정 누락
PM2를 설정할 때 NODE_ENV를 설정하지 않아 기본값인 development 환경으로 실행된 것이다.
package.json의 start 스크립트에 NODE_ENV=production을 명시해놨다고 해도 PM2 실행할 때 설정하지 않았다면 적용되지 않는다.
"scripts": {
"start": "NODE_ENV=production node app.js",
"dev": "NODE_ENV=development node app.js"
}
❗️ PM2는 별도로 환경 변수를 지정하지 않으면 기본값으로 애플리케이션을 실행한다. 그래서 production 환경에서 실행되어야 할 애플리케이션이 development 환경으로 실행되었다.
해결
1. PM2가 관리중인 모든 프로세스를 삭제
$ pm2 delete all
[PM2] Applying action deleteProcessId on app [all](ids: [ 0 ])
[PM2] [app](0) ✓
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
[PM2][WARN] Current process list is not synchronized with saved list. App app differs. Type 'pm2 save' to synchronize.
2. PM2 완전히 종료
$ pm2 kill
[PM2][WARN] No process found
[PM2] [v] All Applications Stopped
[PM2] [v] PM2 Daemon Stopped
3. NODE_ENV를 production으로 설정하여 PM2 실행, 실행중인 프로세스의 이름을 "app"로 지정
$ NODE_ENV=production pm2 start app.js --name "app"
[PM2] Spawning PM2 daemon with pm2_home=/home/ubuntu/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /home/ubuntu/myProject/app.js in fork_mode (1 instance)
[PM2] Done.
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0 │ app │ fork │ 0 │ online │ 0% │ 44.5mb │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
[PM2][WARN] Current process list is not synchronized with saved list. App app differs. Type 'pm2 save' to synchronize.
--name 옵션을 사용해 프로세스 이름을 설정하는 것이 필수는 아니지만 PM2 운영할 때 유용하다.
프로세스 이름을 설정할 경우 pm2 restart app, pm2 stop app 이런식으로 PM2 명령어를 사용할 때 이름으로 작업할 수 있다.
필자는 "app"이 아닌 프로젝트명을 프로세스 이름으로 지정해 사용하고 있다.
4. 현재 실행 중인 PM2 프로세스 상태를 저장
$ pm2 save
[PM2] Saving current process list...
[PM2] Successfully saved in /home/ubuntu/.pm2/dump.pm2
5. PM2로 시스템이 자동으로 시작되도록 설정
$ pm2 startup
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /home/ubuntu/.npm-global/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu
$ sudo systemctl restart caddy
필자는 caddy를 설정했기 때문에 명령어가 다를 수 있다.
혹시 caddy에 대해 궁금하신 분들은 아래 글을 참고해주세요!
2024.06.29 - [Services/AWS] - [AWS] Caddy로 도메인 연동 및 HTTPS 활성화하기
확인
✔️ PM2로 관리 중인 애플리케이션의 실시간 로그 출력
$ git logs
"Loaded environment from .env.local" 라고 확인됐던 메시지가
"Loaded environment from .env.production" 으로 바뀌었다!
$ netstat -tuln | grep LISTEN
pm2 재설정 전
pm2 재설정 후 3000포트 리스닝이 확인된다!
환경 변수 설정이 기본이면서 중요하다는 것을 또 한번 느꼈다.
npm scripts와 PM2의 환경 변수 처리 방식이 다르다는 것을 이해했고 앞으로 배포 프로세스를 더 견고하게 설계해야겠다고 생각했다.
이 경험이 안정적인 서비스 운영을 위한 계기가 되었다.