Nodejs MongoDB Container 만들기

DG
11 min readDec 21, 2019

--

docker로 nodejs, mongodb 를 배포하는 방법에 대해서 배워볼꺼에요.

위의 레포지토리에서 clone 한 프로젝트에서 docker 관련 파일을 모두 삭제하신다면 제가 공부할때 이용한 프로젝트와 똑같은 프로젝트를 가지고 실습 하실 수 있으실거에요. 위의 프로젝트는 docker 를 이용한 배포를 실습해보기 위해서 만들어진 아주 단순한 프로젝트이기 때문에 별 내용이 없어요! express 와 ejs 를 이용해서 만들어진 아주 간단한 todolist 프로젝트입니다.

index.js

const express = require('express');const mongoose = require('mongoose');const bodyParser = require('body-parser');const app = express();app.set('view engine', 'ejs');app.use(bodyParser.urlencoded({ extended: false }));// Connect to MongoDBmongoose.connect('mongodb://mongo:27017/docker-node-mongo',{ useNewUrlParser: true }).then(() => console.log('MongoDB Connected')).catch(err => console.log(err));const Item = require('./models/Item');app.get('/', (req, res) => {Item.find().then(items => res.render('index', { items })).catch(err => res.status(404).json({ msg: 'No items found' }));});app.post('/item/add', (req, res) => {const newItem = new Item({name: req.body.name});newItem.save().then(item => res.redirect('/'));});const port = 3000;app.listen(port, () => console.log('Server running...'));

index.js 파일을 살펴보시면, mongodb 에 커넥션을 요청하는 부분에 localhost가 아닌 mongo 라고 적혀져 있어요. 일반적으로 로컬환경에서 작업하실때면 localhost를 호스트 주소로 입력하실텐데, 지금은 mongo 라고만 적혀있죠? 이건 앞으로 우리가 만들 mongo container 서비스의 이름입니다.

이제 프로젝트에 docker container를 만들어주기 위해서 Dockerfile 을 만들어주도록 해요.

Dockerfile

FROM node:10

첫번째로 우리는 nodejs 를 사용할 것이기 때문에, FROM node 를 적어줍니다. 그 이후에는 node의 어떤 버전을 사용할 것인지에 대해서 명시해주면 되는데요, 간단히 node:latest 라고 적어주신다면 항상 nodejs 의 최신 버전을 이용한 container 를 만들어주실 수 있으시지만, 이후에 nodejs 의 버전이 여러번 업데이트 되어서 해당 파일과 충동이 생기게 될 경우를 대비하면, 자신이 작업을 하였던 특정한 버전에 맞추어서 적어주시는게 더 좋겠죠? 저는 현재 제가 사용하고있는 10 버전을 적어주었습니다 :)

FROM node:10WORKDIR /usr/src/app

두번째로는 WORKDIR 를 설정해주었는데요, 이는 기본적으로 우리의 앱이 container의 어디에 존재할지, path 를 명시해주는 부분입니다.

그리고 package.json 파일과 package-lock.json 파일을 우리의 container 내부로 옮겨줄 수 있어야 합니다. nodejs 어플리케이션은 기본적으로 어떤 dependencies 를 사용하고 있는지에 대해서 package.json 파일에 정보를 담아두기 때문에, container 가 어플리케이션을 제대로 구동해주기 위해선 꼭 필요한 파일들이죠.

해당 작업을 위해 다음과 같은 코드를 한 줄 더 추가해주세요

FROM node:10WORKDIR /usr/src/appCOPY package*.json ./

package.json 파일을 우리의 WORKDIR 에 복사해둔다는 뜻 입니다.

FROM node:10WORKDIR /usr/src/appCOPY package*.json ./RUN npm installCOPY . .EXPOSE 3000

package.json 파일들을 모두 WORKDIR 에 복사해두시고, npm install(해당 앱에 필요한 모든 dependencies 를 추가해줄 수 있도록) 명령어를 실행하도록 RUN npm install 을 적어주세요. 그러면 우리의 container 에는 필요한 모든 dependencies 가 생성이 될 거에요. 그 이후에 container 에 모든 파일들을 복사해 주기 위해서 COPY . . 를 적어주시고, 3000 port에서 시행하겠다는 뜻으로 EXPOSE 3000 을 그 밑에 적어주세요!

package.json

{"name": "docker-node-mongo","version": "1.0.0","description": "","main": "index.js","scripts": {"start": "node index.js"},"keywords": [],"author": "","license": "ISC","dependencies": {"body-parser": "^1.18.3","ejs": "^2.6.1","express": "^4.16.3","mongoose": "^5.2.7"}}

package.json 파일의 scripts 부분을 살펴보시면(scripts 부분) npm start 라는 명령어를 입력해야지만 앱이 실행된다는 것을 알 수 있습니다. 우리의 컨테이너가 어플리케이션을 구동시키려면 해당 커맨드 명령어를 입력해주어야 서버가 제대로 돌아가게되겠죠?

FROM node:10WORKDIR /usr/src/appCOPY package*.json ./RUN npm installCOPY . .EXPOSE 3000CMD ["npm","start"]

위와 같이 CMD [“npm”,”start”]를 추가해줍니다.

위의 Dockerfile의 모습이, 가장 평범하고 단순한 형태의 포맷입니다. 어떤 앱의 어떤 버전을 이용해줄 것인지를 먼저 명시해주고, 작업할 WORKDIR 를 정해주고, 어떤 포트에서, 어떤 명령어를 실행시킬건지에 대한 정보 등을 명시해주는 거에요.

이제 우리는 위의 container를 build 시키고 구동시킬 수 있지만 제대로 동작하진 않을거에요. 왜냐하면 우리의 application은 mongodb 와 연결하려고 mongodb 를 찾게되겠지만 우리의 현재 container는 mongodb 를 가지고 있지 않기 때문이에요.

우리는 위와 같은 방식으로 mongodb container를 새로 명시해줄수 있습니다!만! docker compose 를 이용해서 더 쉽고, 효율적이게 mongodb container 를 설치하고 우리의 컨테이너와 연결시켜 줄 수 있습니다. 해당 방식에 대해서 알아보도록 해요!

docker-compose.yml

version: '3'services:   app:      container_name: docker-node-mongo      restart: always      build: .      ports:         - '80:3000'      links:         - mongo   mongo:      container_name: mongo      image: mongo      ports:         - '27017:27017'

저는 docker-compose version 3를 사용하도록 할거구요, 제가 구동시킬 서비스는 현재 총 2개가 있죠. 바로 nodejs 어플리케이션과 mongo db 입니다. nodejs 어플리케이션은 app 이라는 이름의 service 로 만들어주도록 할께요.

container_name 은 제가 container 를 지칭할때 docker-node-mongo 라는 이름으로 지칭하도록 할꺼구요, 해당 서비스는 image 를 docker hub 에서 끌어다 쓰는 것이 아니고 저희가 직접 작업한 Dockerfile 을 이용해서 build 한 image 를 가져다 쓸 것이기 때문에, build: . 라고 적어주었습니다. 현재 경로에서 Dockerfile을 찾아서, 그 파일로 빌드된 이미지를 사용하겠다라는 의미입니다.

ports 같은 경우에는 local 일 경우에는 80번 포트, 배포 환경에서는 3000번 포트라는 뜻이구요, links 같은 경우에는 이후에 만드는 또다른 컨테이너인 mongo 라는 컨테이너와 연결해줄 것이다 라는 의미입니다. restart always 같은 경우에는 기본적으로 뭔가 문제가 생겼을때 자동으로 재시작 시켜주겠다라는 의미입니다.

mongo service 같은 경우에는 docker hub 에서 이미 만들어진 이미지를 가져다 쓰는 것이기 때문에 더 쉽습니다.

이제 마지막으로 제가 추가해주고 싶은 파일은

.dockerignore

node_modules

gitignore 파일과 같은 역할을 해주는 녀석이라고 생각하시면 됩니다

이제 본격적으로 저희가 지금까지 만든 container 를 구동시켜 볼 텐데요,

docker-compose up

다음 명령어를 쳐서 저희가 만들어준 docker-compose 파일을 실행시켜줍니다. 컨테이너들을 준비시키고 동작시킬 수 있게끔요!

해당 명령어가 완료되었으면 localhost:80 번 포트로 들어가서 우리의 어플리케이션이 제대로 동작하는지 확인도 해 볼 수 있습니다.

저같은 경우에는 다행히 잘 돌아가네요!

이런식으로 컨테이너에 담아서 배포를 하게 될 경우, nodejs와 mongodb가 해당 서버에 설치되어져 있지 않더라도, 위의 컨테이너만 배포해주신다면 어떤 환경에서든지, 버전 충돌에 관한 걱정 전혀 없이 바로 배포를 시켜줄 수 있어요 :)

이제 docker를 이용해서 컨테이너를 생성 및 배포 하는 방법에 대해서 배워봤으니, 해체하는 방법에 대해서도 알아보도록 해요.

일단 가장 단순한 방법으로는 terminal 에서 ctrl + c 를 눌러주시면 바로 nodejs 앱과 mongodb 를 동시에 중지시킬 수 있습니다.

만약에 docker container 를 background에서 실행시키고 싶으시다면

docker-compose up -d

라고 명령어를 입력해주시면 되요. background 로 실행시킨 container 를 중지시켜주고 싶으시다면 docker-compose stop 명령어를 입력해주시면 됩니다!

docker-compose down

이라는 명령어를 한번 입력해보도록 할께요

ctrl + c 를 눌러서 단순 프로세스를 죽이는게 아니라, docker-node-mongo, mongo container를 제거함과 함께 docker-node-mongo_default 라고 자동으로 생성된 network 까지 없애주었습니다. 이제 이러고 다시 docker-compose up 명령어를 실행시켜주게 되면, 다시 network를 구축해주고, container들을 다시 만들어서 실행시켜주기 때문에 이전 database 에 들어있던 내용들은 모두 사라지게 되겠죠?

우리는 docker-compose up 명령어를 시행할때 우리도 모르는 사이에 docker-node-mongo_default 라는 network 를 하나 만들어주고, docker-node-mongo 와 mongo container 를 그 위에 올려서 돌아가게 만드는 것이거든요. network 가 지워졌다고 너무 속상해하진 마세요! docker-compose up 명령어로 언제든지 다시 네트워크를 구축해 줄 수 있으니까요.

자주 사용할법한 docker-compose 명령어들이에요.

이번에 제가 다니고 있는 학교의 모바일 전용 인트라넷 서버 배포는 docker 를 이용해서 해봐야겠어요.

--

--

DG
DG

Written by DG

한국의 iOS 개발자이다. 강아지와 운동을 좋아함. github: https://github.com/donggyushin

No responses yet