nodejs + pm2 application을 구성한 dockfile을 구성하는 방법에 대해서 알아보도록 하겠습니다.
먼저 code를 어떤 방법으로 배포할지에 대한 process를 정하는 것이 중요합니다. 이는 Dockerfile을 어떻게 만들지에 대한 방향이 결정나게 됩니다.
배포 Process
제가 구성한 Docker를 이용한 배포 process는 다음과 같습니다.
nvm 설치nvm을 이용한 node 설치pm2 설치ssh 인증 + git clone 을 통한 code downloadnpm install.pm2/logs 위치에 따른 host 파일 공유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
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 7.3.0
RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash
SHELL ["/bin/bash", "-c"]
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
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
RUN mkdir /root/.ssh
COPY [ "id_rsa", "/root/.ssh/id_rsa" ]
RUN chmod 600 /root/.ssh/id_rsa
COPY [ "do-ssh.sh", "/root/do-ssh.sh" ]
RUN chmod 777 /root/do-ssh.sh
SHELL ["/bin/sh", "-c"]
RUN /root/do-ssh.sh
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을 하는 구성입니다.
RUN mkdir /apps
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
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 8000
EXPOSE 5000
VOLUME /root/.pm2/logs
5. 뒷처리과정
매우매우 위험한 파일을 container에 넣어둔것을 기억하고 있어야지됩니다. private key가 바로 그것이지요. 꼭 이 파일을 지워주는 과정이 필요합니다. 마지막으로pm2 실행에 대한 ENTRYPOINT와 CMD 설정이 필요합니다. 제가 만든 application은 설정 json파일에 따라서 동작환경이 변경되게 됩니다. 설정 json파일을 외부에서 parameter로 넣어줄 수 있도록 설정해주는 것이 필요합니다.
RUN rm /root/.ssh/id_rsa
ENTRYPOINT [ "pm2-docker" ]
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의 형태에 따라, 개발환경에 따라 많은 차이를 가지고 오게 됩니다. nodejs, python, ruby와 같이 외부 library를 받아 compile하는 과정을 가지게 된다면 image내부에서 code를 직접 git으로 받아올 필요가 있습니다. 그러나, JAVA, C#, 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
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 7.3.0
RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash
SHELL ["/bin/bash", "-c"]
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
RUN npm install -g pm2
RUN mkdir /root/.ssh
COPY [ "id_rsa", "/root/.ssh/id_rsa" ]
RUN chmod 600 /root/.ssh/id_rsa
COPY [ "do-ssh.sh", "/root/do-ssh.sh" ]
RUN chmod 777 /root/do-ssh.sh
SHELL ["/bin/sh", "-c"]
RUN /root/do-ssh.sh
RUN ssh -T -v git@10.1.95.184 -o StrictHostKeyChecking=no
RUN mkdir /apps
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
RUN npm install
EXPOSE 8000
EXPOSE 5000
VOLUME /root/.pm2/logs
RUN rm /root/.ssh/id_rsa
ENTRYPOINT [ "pm2-docker" ]
CMD ["pm2/dev-system.json"]
Happy Coding~