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
# 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의 형태에 따라, 개발환경에 따라 많은 차이를 가지고 오게 됩니다. 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
# 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~