nodejs 프로젝트 실행에 docker 사용하기

nodejs 프로젝트를 실행하기 위해서는 nodejs를 설치하면 되겠지만, 다양한 이유로(nodejs의 여러 버전을 사용해야 한다든지...) 시스템에 설치하기 어려울 수 있다. 이런 경우 docker를 통해 nodejs를 사용하는 방법을 소개한다.

목표로 하는 사용 방식

proj라는 디렉토리에 package.js를 포함한 nodejs 프로젝트가 있다고 가정하자. nodejs를 설치하지 않았으면 기본적으로 node나 npm 명령어를 사용할 수 없다. 일단 해당 디렉토리로 이동 후 node6 [port] 명령을 입력하면 nodejs 환경이 준비된 docker 컨테이너 안으로 들어가게 되고 npm install 등 원하는 명령어를 사용할 수 있게 된다. 작업을 마치면 exit을 통해 컨테이너를 빠져나온다.

user@host:~$ cd proj
user@host:~/proj$ node6 5000
user@208c961b05bd:/work$ npm install
...
user@208c961b05bd:/work$ npm start
...
user@208c961b05bd:/work$ exit
user@host:~/proj$

이후 설명은 node6 명령어를 만들어가는 과정이다.

명령어마다 일회성 컨테이너 생성하기

docker를 사용한 방법도 여러 가지가 있다. 하나의 컨테이너를 생성 후 프로젝트 개발 기간 동안 계속 사용할 수도 있지만 여기서는 일회성 컨테이너를 사용한다.

예를 들어 다음과 같이 모듈 설치를 할 수 있다.

user@host:~/proj$ docker run --rm -v ${PWD}:/work node sh -c 'cd /work; npm install'
...
user@host:~/proj$

docker run에 사용된 각각의 파라메터의 의미는 다음과 같다.

  • --rm 작업 실행 후 컨테이너를 삭제
  • -v ${PWD}:/work 현재 디렉토리를 컨테이너 안의 /work 디렉토리에 공유
  • node node 이미지를 기반으로 컨테이너 생성
  • sh -c ‘cd /work; npm install’ 컨테이너 안의 /work 디렉토리에서 npm 모듈 설치

같은 방법으로 프로젝트 실행은 다음과 같이 할 수 있다.

user@host:~/proj$ docker run --rm -v ${PWD}:/work node sh -c 'cd /work; npm start'

작업하는 동안 컨테이너 유지하기

매번 긴 명령어를 치는 것이 번거롭다면 혹은 컨테이너의 작업환경이 계속 유지되어야 하는 상황이라면 다음과 같이 컨테이너 안으로 들어가는 것이 나을 수 있다.

user@host:~/proj$ docker run -it --rm -v ${PWD}:/work node sh -c 'cd /work; bash'
root@208c961b05bd:/work# npm install
...

컨테이너 안에서는 npm start 등의 명령어들을 바로 사용할 수 있다. exit을 통해 빠져나오면 컨테이너는 삭제된다.

생성되는 파일들의 권한 변경

docker 컨테이너 안에서는 root 계정이 기본이기 때문에 node_modules나 로그 파일 등 실행과정에서 생성되는 파일들의 소유주는 root가 된다. 이를 변경하기 위해 다음과 같이 강제로 uid와 gid를 지정해서 들어가는 방법이 있다. (현재 계정의 uid/gid를 1000/1000으로 가정)

user@host:~/proj$ docker run -it --rm -u 1000:1000 -v ${PWD}:/work node sh -c 'cd /work; bash'
I have no name!@ee343d44e8f7:/work$

uid와 gid를 1000번으로 직접 입력하지 않고 docker를 실행하는 계정의 정보를 사용하고 싶다면 다음과 같이 하면 된다.

user@host:~/proj$ docker run -it --rm -u $(id -u):$(id -g) -v ${PWD}:/work node sh -c 'cd /work; bash'
I have no name!@ee343d44e8f7:/work$

하지만 저 uid와 gid는 실제로 컨테이너 안의 시스템에는 없는 uid와 gid 이므로 컨테이너 안에서 이름과 그룹이 제대로 표시되지 않는다. 컨테이너 안에서 계정을 추가할 수도 있겠지만 매번 하기는 번거로우니 내 계정이 추가된 새로운 이미지를 만들어 보자.

user@host:~/proj$ docker run -it --name node6 node sh -c "groupadd -g $(id -g) $(id -gn) && useradd -u $(id -u) -g $(id -g) -m $(id -un)"
user@host:~/proj$ docker commit node6 node6
user@host:~/proj$ docker rm node6

node6 라는 이름의 새로운 docker 이미지가 생성되었다. 이 이미지를 이용해 컨테이너 안으로 들어가 보자.

user@host:~/proj$ docker run -it --rm -u $(id -u):$(id -g) -v ${PWD}:/work node6 sh -c 'cd /work; bash'
user@ee343d44e8f7:/work$

이름과 그룹이 정상적으로 설정된 상태이고 이 상태에서 공유 폴더에 파일을 생성하면 호스트에서도 소유주가 내 계정이 된다.

이런 방식으로 계정 외에도 미리 설치되어야 할 프로그램이 있다면 자신에게 맞는 docker 이미지를 미리 만들어 두면 된다.

포트 열기

웹 서버 프로젝트 같은 경우 포트를 열어야 호스트에서 웹 브라우저로 접속할 수 있다. 다음과 같이 -p 옵션을 사용해 3000번 포트를 열 수 있다.

user@host:~/proj$ docker run -it --rm -u $(id -u):$(id -g) -p 3000:3000 -v ${PWD}:/work node6 sh -c 'cd /work; bash'

bash 함수 작성

nodejs 작업 환경을 시작하기 위해 매번 긴 명령어를 칠 수는 없으니 bash 함수 기능을 이용해 다음과 같이 node6 함수를 정의할 수 있다.

node6() {
local PORT_ARG=""
if [[ $1 ]]; then
PORT_ARG="-p $1:$1"
fi
docker run -it --rm -u $(id -u):$(id -g) ${PORT_ARG} -v ${PWD}:/work node6 sh -c 'cd /work; bash'
}

이제 node6만 치면 nodejs 환경이 시작되도록 할 수 있다. 포트를 열기 원하면 node6 3000이라고 치면 된다. 항상 사용할 수 있게 하려면 함수 정의를 .bashrc 파일 추가하면 된다.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.