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 부분으로 구성됩니다.
- Registry : 생성된 Image를 저장하는 공간입니다. Docker Hub를 의미합니다.
- Repository : 레지스트리 내의 폴더입니다. Git Repository와 유사한 개념입니다.
- 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 파일로 생성합니다.
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
'Programming' 카테고리의 다른 글
[Security] CSRF란? (0) | 2022.06.14 |
---|---|
[Database] sequelize node.js mysql example 간단 예제 (0) | 2022.06.12 |
[Docker] 도커 사용하는 이유? (0) | 2022.06.10 |
[Docker] Ubuntu 우분투 20.04 LTS 도커 설치 방법 (0) | 2022.06.10 |
[Security] OAuth 2.0란? ( 개념 + 인증방식 ) (0) | 2022.06.09 |
댓글