3. Backend 배포하기

 

배포에는 두 가지 라이브러리를 사용할 예정이다. 

App containerize 에는 docker, 그리고 node process management 에는 PM2.

 

구조적으로 보면 VM 내에 backend 와 frontend 두개의 레퍼지토리가 있고, 이 위에 도커가 존재하며 back container / front container 각각을 컨테이너로 분리한다. pm2 는 back container 내에 프로세스 매니징 툴로 이식 된다.

 

 

 

(1) PM2 node process manager 적용

 

 

PM2 를 쓰는 이유? 가장 보편화되고 안정적인 node process manager이기 때문에

 

 

 

npm 으로 pm2 를 먼저 설치한 후 ecosystem.config.js 파일 내에 module config 를 작성해준다. 온라인에 찾으면 많은 예시들이 있을 것이다. 어려울 부분이 없으니 차근차근 작성한 후 local 에서 node를 pm2 로 실행시켜보자.

 

pm2 start ecosystem.config.js 
pm2 status 
pm2 restart 0 / 1 / 2 ...
pm2 logs 0 / 1 / 2 ...

 

 

 PM2 status 를 확인해보면 두 개의 클러스터가 돌고 있는 것을 확인할 수 있다.

클러스터를 두 개로 한 이유는, 한개의 클러스터가 모종의 이유로 멈춰버렸을 시 pm2 가 두 번째의 클러스터를 돌리도록 하기 위함이다. 

 

서버의 부하가 심할 일도 없고, 어떠한 이유로도 멈출 가능성은 많지 않지만 prod 에 적용될 몇 가지 테스트를 진행하기 위해  클러스터를 두가지로 분리해주었다. 나중에 부하 테스트로 첫 번째 cluster를 강제로 멈춰볼 생각이다. 

 

 

하나의 node application 을 두개의 클러스터로 run 시켰다

 

 

 

(2) Docker - containerize

 

 

Server / Source managing 이 끝났으니 backend app 을 컨테이너화 시켜야 한다. 

VM 에 docker 설치를 진행한 후, nest-app root directory 에 Dockerfile을 생성해준다. Dockerfile은 도커 명령어를 실행시키기 위한 package.json 에 가깝다고 보면 좋을 것 같다. 

 

docker-compose.yml 파일로 config 를 푸시하는 과정도 있는데 그 과정은 따로 정리하기로 하고 일단 컨테이너화부터 시켜보자.

 

지금은 당장 docker-compose.yml이 필요하지 않다. 

pm2 를 사용하여 node process를 관리하고 있으므로 

 

Dockerfile 도 아래와 같이 작성해주면 된다.

 

FROM node:18
RUN mkdir -p /var/app
WORKDIR /var/app
COPY . .
RUN npm install -g pm2
RUN npm install --force
RUN npm run build
EXPOSE 4040
CMD ["pm2-runtime", "start", "ecosystem/development/ecosystem.config.js", "--env"]

 

 

일반적으로 document에서 제시하는 Dockerfile format 과 다른점은 pm2-runtime 을 cmd로 사용하고 있다는 점이고, 이를 위해 npm install -g -pm2 를 먼저 실행시켰다.

package.json 에 pm2 가 잘 들어가 있는 것을 확인하였는데, npm install 시에 왜 제대로 설치되지 않는 것인지 이유를 잘 모르겠다. 꼭 -g 명령어로 전역 설정을 해주어야 제대로 돌아가더라. 해당 내용도 왜그런지 찾아봐야겠다.

 

무튼간에 WorkDir /var/app으로 맞춰두었고, 나 같은 경우 ecosystem.config.js 파일을 root directory 에서 관리하는 것이 아니라 환경에 따라 세 가지로 분류하여 관리하였기 때문에,  CMD 내에 정확한 ecosystem.config.js 위치를 적어주었다.

 

 

{"originWidth":1870,"originHeight":316,"style":"alignCenter","caption":"ecosystem/development

 

 

Dockerfile 작성이 끝나면 container 를 생성해주자. 

 

 

// docker container 생성. -t 는 태그. tag 는 optional이니까 굳이 안넣어도 되긴하다. 
sudo docker build . -t your-app-name:tag

// docker container run 명령어. 
// -d 는 detached : container를 background에서 실행시키고, 터미널은 다른 커맨드 실행을 위하여 해당 컨테이너에서 분리.
// -p 는 port : host port는 앞에 오고, container port는 뒤에 온다.  
sudo docker container run -d -p 4040:4040 your-app-name

sudo docker ps
sudo docker stop CONTAINER_ID
sudo docker images
sudo docker rm CONTAINER_ID (컨테이너 삭제 - stop 이후 사용)
sudo docker rmi IMAGES_ID --force (이미지 삭제 - container stop 되어야 삭제 가능)\

// pm2 process monitoring
sudo docker exec -it {컨테이너이름} pm2 list

// 실행중인 pm2 로그 확인
sudo docker exec -it {컨테이너이름} pm2 log {pm2 list 중 하나. ex) nest-app}

 

 

최상단에 위치한 명령어 부터 실행시켜보며 container 가 생성되었는지와 running status, 그리고 pm2 를 통한 container 내의 node process monitoring 까지 진행해본후 디버깅 과정을 마무리하면 백엔드 배포는 끝났다고 보면 된다. 

 

 

 

 

 

'Deployment > Guide' 카테고리의 다른 글

Deployment 2 - DNS / NGINX  (0) 2023.10.30
Deployment 1 - VM  (0) 2023.10.30

2. DNS 설정하기

 

Deployment 1 에서 생성한 vm에서 application을 배포하였다고 가정하자.

VM에서 돌고 있는 Frontend / Backend - local server 인 localhost:3000 / localhost:4040로 어떻게 외부 요청을 받아 넘겨줄까?

Azure Portal의 리소스 그룹 -> 네트워크 설정에서 확인할 수 있는 Public IP 로 요청을 날리면 된다. Public IP + port 로 날리면 되는 것이다. 다만 Public IP와 port 정보를 외부에 공개하는 것은 보안상 문제가 되기에 DNS 관리를 통하여 이 주소를 매핑해주는 것이 좋다.

 

그래서 할일은 -> DNS 호스팅을 통하여 URL을 매핑하고 nginx 를 통해 vm과 인증을 거쳐 연동시키는 과정이다.

좀 복잡하니 잘 보면 좋겠다. 

 

(1) VM access -> Nginx 설치 -> Certbot SSL 설치 -> DNS 설정

 

 

 

 

// 1. ssl 설치

sudo apt-get update

sudo apt-get install certbot -y => certbot 설치


// 2. access token 발급을 위한 여러 단계를 거친다. yes 로 넘어가다가 token을 받는 시점에 잠깐 스톱 & DNS 호스팅 플랫폼에 세팅을 한 후 다음 스테이지 yes 로 넘겨야 한다. 

sudo certbot certonly --manual

마지막에 _acme-challenge 값 나오면 DNS 호스팅 플랫폼에 세팅

 

 

2. 번에서 token 을 받는 시점에 DNS 호스트 설정 해주고, ( 해당 첨부 화면처럼 ) 그 다음 스탭으로 yes 눌러 넘어간다.

 

 

 

// 3. nginx 설치

sudo apt-get install nginx -y => Nginx 설치

cd /etc/nginx/sites-available => Nginx config 설정 위한 폴더로 이동

sudo vi default  => Nginx config 설정 위한 폴더로 이동

 

 

nginx 를 설치하고 나면 cd /etc/nginx 경로로 들어간 후 sites-available 이라는 폴더가 생성되었는지 확인한다. 

해당 폴더 안에 있는 default 파일을 통하여 nginx 설정을 업데이트 해주면 된다.

 

 

 

 

sudo vi default 라는 명령어를 입력하면 아래와 같은 화면이 보이게 되는데 server { listen 80 default ~~ } 에 해당하는 첫 번째 객체 부분 다음에 동일한 포멧이지만 조금은 다른 내용으로 설정을 추가해주면 된다. 수정 할 때 Insert 기능으로 전환하기 위해 i 누르는 것 잊지 말자.

 

 

i 를 누르면 밑에 Insert 라고 나온다.

 

// default 입력 되어 있던 부분.

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _; # Catch all server_name.

    location / {
        try_files $uri $uri/ =404;
    }

    # Redirect HTTP to HTTPS
    return 301 https://$host$request_uri;
}

// port 443 으로 추가 입력한 부분.
// YOUR_DOMAIN 으로 표시해둔 부분은 ssl 진행하는 시점에서 certbot이 터미널에서 물어 보았던 your domain 그대로 입력하면 된다. 

server {
    listen 443 ssl;
    server_name ${YOUR_DOMAIN};

    root /var/www/html;

    ssl_certificate /etc/letsencrypt/live/${YOUR_DOMAIN}/fullchain.pem; # Managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/${YOUR_DOMAIN}/privkey.pem; # Managed by Certbot

    # https websocket
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;

    location / {
        proxy_pass http://localhost:3000;
    }

    location /apis {
        proxy_pass http://localhost:4040;
    }
}

 

 

 

이 정도 입력하였다.

 

입력한 후에는 esc 누르고 :wq! (write and quit) 입력 후 enter. 

 

주목해야 할 부분은 내가 입력해둔 server 443의 location / { proxy_pass http://localhost:3000} 과

location /apis { proxy_pass http://localhost:4040} 파트다.

 

{YOUR_DOMAIN}으로 들어온 요청은 localhost:3000 으로 연결 될 것이고, {YOUR_DOMAIN}뒤에 /apis 라는 prefix 가 붙은 요청들은 VM 에서 돌고 있는 localhost:4040 으로 request가 pass 된다는 의미이다. 

 

예를 들어, DNS 에서 example.com을 당신의 도메인으로 설정해두었다면, localhost:3000 (Frontend) 에 대한 요청은 example.com 으로 맵핑되고 localhost:4040/apis (backend) 에 대한 요청은 example.com/apis 로 맵핑된다고 이해하면 좋겠다. 

 

 

 

 

DNS / Nginx 설정 끝.

'Deployment > Guide' 카테고리의 다른 글

Deployment 3 - Backend (Nest.js)  (0) 2023.10.30
Deployment 1 - VM  (0) 2023.10.30

- 배포 환경 : Azure Portal

- DNS : Gabia

- Backend Server : Nest.js, Pm2 (process manager), Docker (App Isolator), ACI (Container Hub)

- Database : MongoDB 

- Frontend : Next.js 

 

1. VM 생성하기

 

 

앱을 배포하기 위해서 자체 서버를 돌리지 않는 이상, 당연히 VM이 필요하다.

마이크로소프트가 제공하는 에저의 클라우딩 서비스를 공부하는 중이기도 하고, 마침 회사에서도 B2B 솔루션을 메인잡으로 하고 있기에 Azure Portal 을 이용하여 VM을 생성하였다. 개인 소영업과 스타트업의 경우에는 AWS를 더많이 사용하는 추세인 듯 하다. 반대로 90%의 Industry Giant들은 MS가 제공하는 애저를 사용한다.

 

 

(1) Azure Portal -> Resource 만들기 -> 가상머신 만들기 

 

 

 

VM 에 필요한 리소스와 가용성, Cloud server location 등은 필요에 따라 맞춰주면 된다. 이미지의 경우 테스트를 위해 Ubuntu Server 중 가장 저렴한 것으로 설정했다.

 

 

아래는 가상머신 만들기의 기본 사항 탭이다. 그 중 관리자 계정 파트는 나중에 VM 에 접근 할 Auth를 설정하는 곳이라고 보면된다.

나와 같은 경우는 인증 형식을 암호로 체크하였다. 직관적이고 익숙한게 좋아서..

 

 

 

 

사용자 이름에는 본인이 사용하고 싶은 이름, 암호에는 본인이 사용하고 싶은 암호를 넣으면 된다. 

이 부분은 나중에 vm 접근 시에 당신이 만든 VM의 "ssh"+ "publicIP" + "-l" + "yourID" 순으로 터미널에 입력된다. 

그 이후에 터미널에서 묻는 query 에 설정한 password 를 입력하면 vm 으로 접근이 된다. 

 

방금 설명한 내용은 아래 참고하면 된다.

 

password 입력시에 안보인다고 쫄지 마시고, 끝까지 잘 입력 후 enter 누르시길.

 

 

(2) 디스크 설정 -> 네트워킹 설정 -> 관리 -> 모니터링 -> 고급

 

나머지는 건드릴 만한 내용이 솔직히 없다. 네트워킹과 같은 경우 인바운드 포트를 눌러보면 HTTP, HTTPS 가 나오는데 이 둘에도 체크를 해주자. 태그 탭에 이르면, VM 에 붙이고 싶은 이름과 값을 입력해주면 된다. 결론적으로 의무적으로 건드릴 부분은 기본사항 / 네트워킹 / 태그 / 검토 + 만들기 정도이다. (나머지는 필요에 의해서.)

 

 

왠만하면 부하 분산 옵션에 Load Balancer 도 체크해주자. 알아서 부하 분산을 체크하고 모니터링 해주는 Azure 자체 서비스다.

 

 

 

VM 생성이 잘 되었고 access 에도 문제가 없다면 docker 를 통한 app containerize 차례다.

아니다 그 이전에 nginx 로 DNS 먼저 잡아보자

'Deployment > Guide' 카테고리의 다른 글

Deployment 3 - Backend (Nest.js)  (0) 2023.10.30
Deployment 2 - DNS / NGINX  (0) 2023.10.30

+ Recent posts