본문 바로가기
Programming

[Docker] Node.js Dockerfile로 배포 하는 방법

by 개발자 염상진 2022. 6. 12.

 

Node.js 웹 어플리케이션 컨테이너화

 

Node.js express 모듈로 서버를 완성한 이 후 배포할 때 Docker를 사용합니다. Docker는 프로세스, 파일 시스템, 네트워크의 독립성을 보장해주고, Dockerfile 혹은 Docker-compose를 사용해 배포 과정을 단순화 할 수 있습니다. 또한 트래픽이 몰리는 상황에서 서버의 수평적 확장을 지원합니다. 도커에 대해 더 자세히 이해하고 싶다면 아래 글을 참고해주세요.

 

 

Docker로 배포할 때는 프로젝트를 완성한 이후 Docker Image를 만들고 실행환경에서 Image를 사용해서 Container를 실행합니다. Docker를 사용하면 프로젝트 실행에 필요한 모든 의존성들을 표준화된 패키징 단위인Container에 담게 됩니다. Container는 리눅스 컨테이너를 사용합니다. 즉, Container는 간단한 리눅스 운영체제라고 보시면 됩니다. 

 

 

Node.js 프로젝트 생성

 

package.json 파일로 프로젝트를 시작합니다.

$ sudo npm init

 

start 항목에 server를 실행하기 위해 node server.js를 추가해줍니다. 

{
  "name": "express-docker",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start" : "node server.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "About-Tech",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.16"
  }
}

 

프로젝트에 필요한 모듈들을 설치합니다. 서버를 자동으로 갱신하기 위해 nodemon을 설치해줍니다.

$ npm i express
$ npm i -D nodemon

 

server 코드를 작성해줍니다. 서버에서는 간단한 문자열을 응답하는 간단한 서버입니다. 

const express = require('express');

const app = express();
const PORT = process.env.PORT || 5001

app.use('/', (req, res)=>{
    res.send("Server is running");
})

app.listen(PORT, ()=>{
    console.log(`Server is on ${PORT}`)
})

 

 

Dockerfile 생성

 

배포를 위해 Dockerfile을 생성합니다.

$ touch Dockerfile

 

Dockerfile에서는 사용할 Image를 선택하고, 워킹 디렉토리를 설정합니다. node는 버전 16을 사용하고, node에서 워킹 디렉토리는 /usr/src/app에 어플리케이션을 추가합니다.

// 사용할 Image 선택
FROM node:16

// 워킹 디렉토리 지정
WORKDIR /usr/src/app

 

Node.js 어플리케이션의 의존성을 설치해줍니다. package.json 및 package-lock.json을 복사합니다. 이 후 npm 모듈 설치해줍니다.

// 앱 의존성 복사 및 설치
COPY package*.json ./

RUN npm install

 

생성할 Docker Image 내에 서버 소스코드를 넣기 위해 COPY 명령어를 사용합니다.

// 앱 소스 코드를 복사해줍니다.
COPY . .

 

서버에서 사용하는 PORT를 바인딩해줍니다. port 바인딩은 EXPOSE 명령문을 사용합니다. 마지막으로 앱을 실행하는 명령어를 지정해줍니다. 서버를 실행하기 위해서는 'node server.js' 명령문이 필요합니다.

// PORT 바인딩
EXPOSE 5001

// 명령문 삽입
CMD ["node", "server.js"]

 

Dockerfile 완성

총 7단계로 구성된 Dockerfile이 완성되었습니다.

FROM node:16

# 앱 디렉터리 생성
WORKDIR /usr/src/app

# 앱 의존성 설치
COPY package*.json ./

RUN npm install
# 프로덕션을 위한 코드를 빌드하는 경우
# RUN npm ci --only=production

# 앱 소스 추가
COPY . .

EXPOSE 5001
CMD [ "node", "server.js" ]

 

.dockerignore 파일 생성

추가적으로 .dockerignore 파일을 생성해줍니다. Dockerfile이 위치한 디렉토리에 .dockerignore 파일을 생성해줍니다. .gitignore와 동일하게 docker Image 파일내에 설치한 모듈을 덮어쓰지 않도록 node_module과 디버깅 로그를 제외합니다.

node_modules
npm-debug.log

 

 

Image Build

생성한 Dockerfile을 사용해서 Image를 빌드합니다. -t 태그를 사용하면 태그를 사용할 수 있습니다. Image는 3 부분으로 구성됩니다.

  1. Registry : 생성된 Image를 저장하는 공간입니다. Docker Hub를 의미합니다.
  2. Repository : 레지스트리 내의 폴더입니다. Git Repository와 유사한 개념입니다.
  3. Tag : Image를 구분하는 식별자입니다.

 

Ubuntu 환경에서 Docker를 사용하면 모든 명령어에 sudo 옵션을 붙여줘야 합니다.

 

sudo docker build . -t <Registry Name>/<Repository Name>:<Tag>

 

7단계의 코드가 차례로 실행되면서 Image가 생성됩니다.

 

생성된 Image 파일을 조회합니다. 새로 생성한 express-docker/node-web:latest와 node 2가지 Image가 저장되었습니다.

$ sudo docker images
REPOSITORY                TAG       IMAGE ID       CREATED              SIZE
express-docker/node-web   latest    1b60121a52e6   About a minute ago   919MB
node                      16        b59df4e04d61   4 days ago           907MB

 

이제 어떤 환경에서든 실행할 수 있는 Docker Image가 완성되었습니다. 개별적인 Image는 Dockerfile로 생성가능합니다. 실제 프로젝트 환경에서는 여러개의 모듈을 사용합니다. 서버는 express, DB는 MongoDB 등 여러개의 모듈을 사용하는 프로젝트를 이미지로 만들 때는 Docker-Compose 파일로 생성합니다. 

 

 

[Docker] Docker Compose 사용법 (도커 네트워크 구성)

Docker Compose 사용 이유 도커(Docker)에서 이미지를 가져와 컨테이너를 실행할 수 있습니다. 도커를 사용하는 근본적인 이유는 컨테이너별로 독립된 공간을 제공하고, 배포를 유연하게 도와주기 때

about-tech.tistory.com

 

Image 실행

생성된 Image를 사용해서 Container를 실행합니다. Container을 백그라운드에서 실행하기 위해서는 -d 옵션을 추가해줍니다. -p 옵션은 Container의 포트와 실행환경의 포트를 연결해줍니다. Image를 실행하면 Container ID가 암호화되어 출력됩니다.

 

sudo docker run -p 5001:5001 -d express-docker/node-web:latest
d9c3cdcc1a33e08861ea6cc10ff9fd2c9db51e14ab710ca1fb7bb0f1bfbc48cd

 

생성된 Conatiner를 조회합니다. 백그라운드 옵션을 지정해 Image를 실행했기 때문에 Container 실행되고 있습니다.

$ sudo docker container ps -a
CONTAINER ID   IMAGE                            COMMAND                  CREATED          STATUS          PORTS                                       NAMES
d9c3cdcc1a33   express-docker/node-web:latest   "docker-entrypoint.s…"   37 seconds ago   Up 36 seconds   0.0.0.0:5001->5001/tcp, :::5001->5001/tcp   xenodochial_antonelli

 

localhost:5001에 접속하면 위에서 작성한 server 파일이 정상적으로 실행됩니다.

 

로그파일을 보기 위해서는 Container ID를 사용합니다.

$ sudo docker logs d9c3cdcc1a33e08861ea6cc10ff9fd2c9db51e14ab710ca1fb7bb0f1bfbc48cd
Server is on 5001

 

실행중인 Container에 접속해서 폴더 내부를 확인하기 위해서는 exec 명령문을 사용합니다. 실행중인 Container에서 bash shell로 실행합니다. shell을 실행하면 Dockerfile에서 지정한 워킹 디렉토리로 접속합니다. 이곳에 작성한 server 파일이 저장되어 있습니다.

$ sudo docker exec -it <Container ID> /bin/bash

 

 

 

Reference

 

 

 

[Docker] 도커 사용하는 이유?

컨테이너 사용 배경? 부산항에서는 무역에 필요한 물동량을 컨테이너를 이용해 처리한다. 대형 트럭이 싣고 전국 구석구석 누비는 컨테이너가 존재하지 않는다면 재래식 방법으로 현재와 같은

about-tech.tistory.com

 

 

[Docker] Ubuntu 우분투 20.04 LTS 도커 설치 방법

How to install Docker in Ubuntu 20.04 LTS? 도커(Docker) 설치방법 ① apt package update $ sudo apt-get update ② Install curl $ sudo apt-get install curl ③ Add Docker official GPG key Docker Engine..

about-tech.tistory.com

 

 

[Security] JWT 토큰 기반 인증이란?

토큰 기반 인증 서버 사이드에서 사용자를 특정하는 방법은 여러가지다. 그 중 대표적인 방법이 세션 인증이다. 세션 기반 인증 방식은 서버 혹은 DB에 사용자를 특정할 수 있는 세션ID를 생성해

about-tech.tistory.com

 

댓글