기존에 개발한 서버를 pm2와 도커를 이용해 기동하려고 하니 수많은 에러를 뿜어 내면서 기동 되지 않았습니다. pm2를 사용하지 않고, 단일 서버에 대해 빌드하여 기동했을 때는 정상적으로 서버를 사용할 수 있었고, 기본적으로 제공하는 pm2 기동 방법에서 최신 자바스크립트 문법을 지원해 주지 않아, 다른 방법을 찾아 보았습니다.
ecosystem.config.js
pm2로 기동하기 위해서는 ecosystem.config.js를 필요로 합니다. npm run build
가 완료되면 src 아래에 있던 소스파일들이 변환되어 dist 파일 아래에 생성되고, 빌드된 서버를 실행하기 위해 dist/index.js
를 실행합니다.
module.exports = [{
script: 'dist/index.js',
name: 'my-server',
exec_mode: 'cluster',
instances: 2
}]
위와 같은 pm2 ecosystem.config.js을 실행하는 경우 에러가 나는 이유는 제가 서버를 es6로 작성하고 실행하였기 때문입니다. 따라서 es6로 작성한 노드 서버 소스를 pm2에서 실행시키기 위해서는 트랜스파일
이 필요하였습니다.
트랜스파일이란?
트랜스파일은 컴파일의 일종으로 한언어로 작성된 소스 코드를 비슷한 수준으로 추상화된 다른 언어로 변환하는 것을 말합니다.
- js es6를 es5로 변환
- C++ 언어를 C로 변환
개발에서 사용하는 babel-node
의 경우 운영환경에서는 사용하지 않아야합니다. 그 이유로는 불필요하게 무겁고, 캐시를 사용하기 위해 많은 메모리를 사용하기 때문입니다. 따라서 노드 서버를 빌드하여 바벨을 사용하지 않고 서버를 동작시킬수 있도록 합니다.
노드 서버를 바벨과 함께 사용하기 위해서는 이 깃헙을 참고하시기 바랍니다.
빌드를 진행하면 src 디렉토리 아래에 모든 소스파일들을 dist 경로 아래로 빌드해주게 됩니다.
package.json에 추가
"scripts": {
+ "build": "babel src -d dist"
}
위와 같이 빌드 스크립트를 추가하고, 서버 디렉토리 경로 아래 dist/index.js를 생성해 pm2로 기동하고자 합니다.
아래 명령어로 빌드를 진행합니다.
npm run build
설치해보니 계속 에러 메세지가 나와서 아래의 패키지를 npm install --save-dev <패키지명>
으로 설치하였습니다.
"@babel/plugin-proposal-numeric-separator": "^7.12.7",
"@babel/plugin-syntax-numeric-separator": "^7.10.4",
"@babel/preset-env": "^7.8.6",
"@babel/preset-modules": "^0.1.4",
"@babel/runtime": "^7.12.5",
위 패키지들을 모두 설치후에 아래와 같이 빌드가 되고 dist
경로에 index.js가 생성된걸 확인 할 수 있습니다.
npm run build
> my-server@1.0.0 build
> babel src/index.js -d dist
Browserslist: caniuse-lite is outdated. Please run the following command: `npx browserslist --update-db`
Successfully compiled 1 file with Babel (528ms).
다 된줄 알고 시원하게 도커에서 빌드 후 실행시켜보니 아래와 같은 에러를 계속 뿜어냈습니다
2021-02-01T13:23:27: PM2 log: App [my-server:1] exited with code [0] via signal [SIGINT]
2021-02-01T13:23:27: PM2 log: App [my-server:1] starting in -cluster mode-
ReferenceError: regeneratorRuntime is not defined
스택오버플로에서 Babel 6 regeneratorRuntime is not defined 글을 통해 조치해봅니다.
npm install --save-dev @babel/plugin-transform-runtime
{
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/transform-runtime"]
]
}
npm run build
명령 수행
FROM node:10
# 앱 디렉터리 생성
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
# pm2 설치
RUN npm install -g pm2
# 프로덕션을 위한 코드를 빌드하는 경우
# RUN npm ci --only=production
# ENV NODE_ENV production
# dockerfile을 실행하는 경로에서 소스 복사
COPY . .
# 아래 포트로 매핑
EXPOSE [원하는 포트]
RUN npm run build
# pm2-runtime으로 실행
CMD ["pm2-runtime", "start", "ecosystem.config.js", "--env", "production"]
위에 작성한 dockerfile을 이용해 서버 이미지를 빌드한다.
docker build -t [닉네임]/[이미지 이름] .
정상적으로 빌드가 완료되면 이미지가 동작되는지 확인한다.
docker run -p 2222:2222 [닉네임]/[이미지 이름]
docker push [닉네임]/[이미지 이름]
위 과정을 통해 node 서버를 빌드하고 빌드한 서버를 docker에서 pm2를 이용해 여러개의 코어에서 동작하도록 살펴보았습니다.
다음으로는 docker hub에 업로드한 이미지를 바탕으로 ec2인스턴스에서 이미지를 실행시켜보도록 하겠습니다.