잊지 않겠습니다.

nodejs + pm2 application을 구성한 dockfile을 구성하는 방법에 대해서 알아보도록 하겠습니다.

먼저 code를 어떤 방법으로 배포할지에 대한 process를 정하는 것이 중요합니다. 이는 Dockerfile을 어떻게 만들지에 대한 방향이 결정나게 됩니다.

배포 Process

제가 구성한 Docker를 이용한 배포 process는 다음과 같습니다.

  1. nvm 설치
  2. nvm을 이용한 node 설치
  3. pm2 설치
  4. ssh 인증 + git clone 을 통한 code download
  5. npm install
  6. .pm2/logs 위치에 따른 host 파일 공유
  7. docker run의 parameter pass를 통한 pm2 start json 파일 전송

1. nvm 설치 & node 설치 & pm2 설치

ubuntu image를 기본으로 하여 구성을 하도록 하겠습니다. nodejs application은 npm install을 통해서 node_modules을 다운로드 받아서 compile되는 환경이기 때문에 build환경역시 갖추는 것이 중요합니다.

FROM ubuntu # 빌드 환경 구성 RUN apt-get update RUN apt-get install -y wget build-essential keychain git python # NVM_DIR, NODE_VERSION에 따른 ENV 설정 ENV NVM_DIR /usr/local/nvm ENV NODE_VERSION 7.3.0 # NVM 다운로드 & 설치 RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash # Shell 변경 (sh -> bash) SHELL ["/bin/bash", "-c"] # nvm 구성 & node install RUN source $NVM_DIR/nvm.sh; \ nvm install $NODE_VERSION; \ nvm use --delete-prefix $NODE_VERSION; ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH # PM2 설치 RUN npm install -g pm2

2. ssh 인증 구성

ssh 인증을 위해서 private key를 image안에 COPY할 필요가 있습니다. 그리고 $(ssh-agent)값을 지정해줄 필요가 있습니다. 그런데, eval을 이용한 값 설정의 경우, Dockerfile에서 할 수 없습니다. 따라서 do-ssh.sh 실행 파일을 구성해서 처리할 image 내부에서 실행할 필요가 있습니다.

다음은 do-ssh.sh파일의 내용입니다.

eval "$(ssh-agent)" && ssh-agent -s ssh-add /root/.ssh/id_rsa
# .ssh Folder작성 & private key Copy RUN mkdir /root/.ssh COPY [ "id_rsa", "/root/.ssh/id_rsa" ] # SSH Key 권한 설정 - 권한이 600이 아닌경우, id_rsa key를 얻어내지 못합니다. RUN chmod 600 /root/.ssh/id_rsa # do-ssh.sh 파일 COPY COPY [ "do-ssh.sh", "/root/do-ssh.sh" ] # 실행권한 설정 RUN chmod 777 /root/do-ssh.sh # SHELL 변경 (bash -> sh) SHELL ["/bin/sh", "-c"] # do-ssh.sh RUN RUN /root/do-ssh.sh # SSH 접근 check. -o StrictHostKeyChecking=no option이 없으면 docker container에서 실행되지 않습니다. RUN ssh -T -v git@10.1.95.184 -o StrictHostKeyChecking=no

3. git code download & npm install

nodejs Application이 위치될 folder를 만들어주고, git clone을 통해서 code를 받고, npm install을 하는 구성입니다.

# apps folder 작성 RUN mkdir /apps # Shell 변경 (sh -> bash) SHELL ["/bin/bash", "-c"] WORKDIR /apps RUN git clone git@10.1.95.184:/home/git/repo/fms-api-v2.git -o StrictHostKeyChecking=no WORKDIR /apps/fms-api-v2 # npm 설치 RUN npm install

npm install을 통해서 필요한 node module들을 모두 받아주고 build과정을 거치게 됩니다.

4. PORT 공유 & PM2 Log volume 구성

제가 만든 application은 5000, 8000번 port를 open시켜서 사용합니다. 사용되는 PORT를 EXPOSE 시켜주는 과정이 필요하게 됩니다. 그리고 pm2의 log 파일을 host에 기록하도록 volume을 추가합니다.

# expose 5000, 8000 port EXPOSE 8000 EXPOSE 5000 # VOLUME 설정 pm2 log folder VOLUME /root/.pm2/logs

5. 뒷처리과정

매우매우 위험한 파일을 container에 넣어둔것을 기억하고 있어야지됩니다. private key가 바로 그것이지요. 꼭 이 파일을 지워주는 과정이 필요합니다. 마지막으로pm2 실행에 대한 ENTRYPOINT와 CMD 설정이 필요합니다. 제가 만든 application은 설정 json파일에 따라서 동작환경이 변경되게 됩니다. 설정 json파일을 외부에서 parameter로 넣어줄 수 있도록 설정해주는 것이 필요합니다.

# Private Key 삭제 RUN rm /root/.ssh/id_rsa # ENTRYPOINT 설정 docker container에서 pm2를 실행시킬때는 pm2-docker를 통해서 실행합니다. ENTRYPOINT [ "pm2-docker" ] # CMD 설정 - parameter가 없는 경우, default 값을 지정하게 됩니다. CMD ["pm2/dev-system.json"]

6. build image & docker run

image를 만들기 위해서, docker build를 다음과 같이 구성합니다.

docker build -t nodejs-pm2-application .

이제 process가 진행되면 nodejs-pm2-application으로 image가 만들어지게 됩니다.

만들어진 image를 이용해서 container를 배포하는 명령어는 다음과 같습니다.

docker run -it --name node-app -p 5000:5000 -p 8000:8000 -v /logs/pm2:/root/.pm2/logs -t nodejs-pm2-application pm2/api-system1.json
  • -p option으로 5000, 8000번 port를 host에 연결합니다.
  • -v options으로 /root/.pm2/logs folder를 host의 /logs/pm2로 mount 시킵니다.
  • 마지막에 command로 /pm2/api-system1.json을 넣어 container의 COMMAND를 pm2-docker pm2/api-system1.json으로 변경시킵니다.

SUMMARY

Dockerfile을 구성하는 것은 Application의 형태에 따라, 개발환경에 따라 많은 차이를 가지고 오게 됩니다. nodejspythonruby와 같이 외부 library를 받아 compile하는 과정을 가지게 된다면 image내부에서 code를 직접 git으로 받아올 필요가 있습니다. 그러나, JAVAC#GO와 같이 universal compile이 되는 경우, Docker image를 만들때, compile시켜 ADD를 통해서 실행파일을 image안에 넣는것이 더 좋을것 같습니다.

다음은 전체 Dockerfile입니다.

FROM ubuntu # 빌드 환경 구성 RUN apt-get update RUN apt-get install -y wget build-essential keychain git python # NVM_DIR, NODE_VERSION에 따른 ENV 설정 ENV NVM_DIR /usr/local/nvm ENV NODE_VERSION 7.3.0 # NVM 다운로드 & 설치 RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash # Shell 변경 (sh -> bash) SHELL ["/bin/bash", "-c"] # nvm 구성 & node install RUN source $NVM_DIR/nvm.sh; \ nvm install $NODE_VERSION; \ nvm use --delete-prefix $NODE_VERSION; ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH # PM2 설치 RUN npm install -g pm2 # .ssh Folder작성 & private key Copy RUN mkdir /root/.ssh COPY [ "id_rsa", "/root/.ssh/id_rsa" ] # SSH Key 권한 설정 - 권한이 600이 아닌경우, id_rsa key를 얻어내지 못합니다. RUN chmod 600 /root/.ssh/id_rsa # do-ssh.sh 파일 COPY COPY [ "do-ssh.sh", "/root/do-ssh.sh" ] # 실행권한 설정 RUN chmod 777 /root/do-ssh.sh # SHELL 변경 (bash -> sh) SHELL ["/bin/sh", "-c"] # do-ssh.sh RUN RUN /root/do-ssh.sh # SSH 접근 check. -o StrictHostKeyChecking=no option이 없으면 docker container에서 실행되지 않습니다. RUN ssh -T -v git@10.1.95.184 -o StrictHostKeyChecking=no # apps folder 작성 RUN mkdir /apps # Shell 변경 (sh -> bash) SHELL ["/bin/bash", "-c"] WORKDIR /apps RUN git clone git@10.1.95.184:/home/git/repo/fms-api-v2.git -o StrictHostKeyChecking=no WORKDIR /apps/fms-api-v2 # npm 설치 RUN npm install # expose 5000, 8000 port EXPOSE 8000 EXPOSE 5000 # VOLUME 설정 pm2 log folder VOLUME /root/.pm2/logs # Private Key 삭제 RUN rm /root/.ssh/id_rsa # ENTRYPOINT 설정 docker container에서 pm2를 실행시킬때는 pm2-docker를 통해서 실행합니다. ENTRYPOINT [ "pm2-docker" ] # CMD 설정 - parameter가 없는 경우, default 값을 지정하게 됩니다. CMD ["pm2/dev-system.json"]

Happy Coding~

Posted by Y2K
,