Docker,docker-compose,mongoose,DB 저장

김하은·2023년 6월 12일
0

도커 컴포즈 실행

docker-compose up

도커 컴포즈 중지

docker-compose stop

도커컴포즈로 시작한 컴퓨터들 지우기

docker-compose down

=> 다만 build시 생성된 이미지들은 따로 삭제 필요
도커 이미지보기

docker images

도커 이미지 전체삭제

docker rmi docker images -a -q

==> down을 하게 되면 mongoDB의 내용들이 전부 삭제된다. 즉, 데이터베이스에 저장되어있던 데이터들도 삭제된다.

그래서 down을 하게되어도 데이터는 살아있게 데이터만 다른 저장공간에 저장해놓기도 한다.
실제 서비스를 공개할때엔 docker을 사용하지 않는다. 이때에는 실제 설치를 하여 사용한다.
지금docker를 사용하는 것은 개발을 수월하게 하기위해 개발자들의 환경을 통일하기 위함이다.

포트포워딩

포트포워딩을 사용하여 포트를 열어주었는데 이것은 내 컴퓨터에서 도커로 접속할때를 열어준것이다.

그럼 도커 컴퓨터 간에 접속을 할 시에는 도커 컴포즈를 사용한다.

docker-compose!! => 도커들을 묶어 도커들간에는 포트포워딩이 없어도 됨.

docker-compose로 docker들을 묶을 수 있는데 이것을 사용하게되면 도커에서 도커로의 포트포워딩이 없더라도 해당 도커컴퓨터 이름만 알려주면 자동으로 docker-compose안에있는 도커들 끼리는 자동으로 연결이 된다.
=> 이름을 가지고 찾는다고 하여 name resolution (네임리졸루션) 이라고한다.

현재 docker-compose에 포트포워딩을 적용해놓았는데 express와 mongoDB-compass를 사용하기 위함이니 이것은 그냥 두도록 한다.
(이 부분이 없더라도 도커끼리는 접속이 가능하다)

여기서!!

Dockerfile.mongo 라는 파일에 FROM mongo:5
이렇게 한줄을 넣어 몽고 5버전을 다운로드받는 것을 작성했다.

이렇게 적는것 솔직히 뭐.. 일종에 낭비 같은게 아닐까 생각이 들었던 찰나, 이렇게 다운로드만 받아오는 코드를 파일생성 없이 바로 docker-compose에 적어놓을 수 있다고 했다.

database-mongo:
    build:
      context: .
      dockerfile: Dockerfile.mongo
      # 포트포워딩을 할 경우 mongoDB-compass 27017번=> 도커 database-mongo로
    ports:
      - 27017:27017

여기 build부분을 넣는대신 image라는 것을 넣어 해당이미지를 다운받아오면 된다.

  database-mongo:
    image: mongo:5
    ports:
      - 27017:27017
     

즉 기존에 Dockerfile.mongo 라는 파일에 있는

FROM mongo:5

이 부분을

docker-compose 파일에 image: mongo:5 이렇게 여기에 적어 넣어주면 Dockerfile.mongo은 더이상 필요 없게된다.

mongoose 설치하여 DB접속, 등록하기

yarn add mongoose

mongoose, mongoDB 각각 docs가 존재한다.
mongoose 가 없어도 mongoDB 사용이 가능하다.

mongoDB를 사용하면 db.collection.find() 등 해당 db의 컬렉션의 데이터를 찾을 수 있는데 이렇게 매번 명령어를 찾고, 외우고 하는것에는 좀 어려울 수 있다.

mongoose는 ODM중 하나로 Object Document Mapping
=> 즉, 객체를 문서에 맵핑시켜주는 도구.

mongoose를 통해 find를 한다고 하면 객체형태로 원하는 조건을 적으면 된다. 그러면 mongoose가 자동으로 mongoDB형태로 바꾸어준다.

즉, 객체 형태로 입력하면 알아서 Document에 자동으로 맵핑되는 것이다.

자동으로 해당하는 DB에 맵핑될 수 있게 바꿔주는 도구가 바로 ORM, ODM이라는 것!!

MongoDB만 사용하는 경우에는
https://www.mongodb.com/docs/manual/crud/
이렇게 몽고DB docs를 보고,

MongoDB와 mongoose를 사용하는 경우에는
mongoose docs
https://mongoosejs.com/docs/index.html
를 함께 볼 수 있다.


mongoose 를 거쳐 MongoDB로 저장되게 하기

따라서 mongoose docs를 중심으로 해보자.

post 는 저장할 데이터를 보내주는 것. 즉, 이 부분에서는 DB에 저장되는 로직이 필요하고,
get은 데이터를 DB에서 꺼내오는 것. 즉, DB에 접속해 데이터를 꺼내오는 로직이 필요하다.

npm에서 mongoose docs를 확인해보자.

import mongoose from 'mongoose';

이렇게 import를 해온다.

그 다음 DB에 연결하는 로직은

mongoose.connect('mongodb://127.0.0.1/my_database');

127.0.0.1 은 localhost이다.
여기서 우리는 도커의 express에서 도커의 mongoDB에 연결할 것이고,
두 컴퓨터는 서로 다름을 알아야한다.
express에서 localhost는 자신이 있는 컴퓨터를 의미한다. 따라서 mongoDB가 있는 컴퓨터를 적어주어야한다.

다행히 docker-compose를 사용해 두 컴퓨터간은 포트포워딩 없이 서로 그룹핑되어 이름만 알면 연결할 수 있다.

localhost대신 해당 mongoDB가 있는 컴퓨터 이름을 적어주고, 추가로 mongo-compass에서 접속할 포트번호를 뒤에 붙여줄 수 잇다.

그 뒤에 /my_database 이 부분은 mongoDB에서 저장될 데이터베이스 이름을 넣어주면 되는데 만약 그 데이터 베이스가 없다면 새로 생성되니 걱정하지 않아도 된다.

모델 만들기

schema라는 것을 사용해 컬렉션을 만든다.
schema는 컬렉션에 들어갈 데이터 구조를 의미한다.
schema를 작성하고, 해당 schema를 바탕으로 모델을 만든다.

// 컬렉션에 들어갈 데이터 구조
const BoardSchema = new mongoose.Schema({
  writer: String,
  title: String,
  contents: String,
});

// schema를 사용해 모델 만들기(즉, 구조를 등록해 컬렉션을 만들기)
export const Board = mongoose.model("Board", BoardSchema);
// Board라는 이름의 모델을 만들고 , 해당 스키마는 BoardSchema이다.

그리고 export하여 index.js파일에서 해당 컬렉션을 사용한다.

데이터를 조회하는 로직(저장된 데이터를 꺼내오는 로직)

get방식
Board.find() 로 export해온 Board를 import하여 Board.find() 이 꺼내온 결과를 변수에 담고 응답으로 보여주는데, 이때 외부로 요청하는 라이브러리 등은 비동기로 작동되어 응답을 다 받은 뒤 아랫줄로 내려갈 수 있게 async/await를 붙이도록 한다.

데이터를 DB에 저장하는 로직

post 방식으로 작성되어 보내는 것은 req.body에 각각 담긴다.
따라서 new Board로 새로운 컬렉션을 만들고, 그 안에 req.body에서 각각 꺼낸 객체를 넣어준다.

const board = new Board({
    writer: req.body.writer,
    title: req.body.title,
    contents: req.body.contents,
  });

이렇게.
그리고 작성된 데이터를 save()를 사용하여 DB에 저장할 수 있다.

이것도 또한 async/await를 붙여준다.

await board.save(); // save를 만나 DB에 저장되러 날라감. ==> mongoose명령어. 얘가 mongoose를 통해 mongoDB명령어로 변환시켜줌.

이렇게 몇줄을 추가해주었고, 이제 서버를 키기 위해 docker-compose를 build해준다.

docker-compose build

이렇게 build를 해주었으면 이제 실행시켜보자

docker-compose up

실행되는 로그를 쭉 보다보면


이렇게 node와 DB가 실행되고있는 것을 볼 수 있다.


docker-compose 내에 도커가 두대 있고, => 하나에는 express가, 하나에는 mongoDB가 있다.

nodemon으로 서버를 실행하면 수정하고 저장을 하면 자동으로 refresh를 하여 반영이 되어야한다.

그런데 지금 도커에서 nodemon이 돌고 있음에도 뭔가를 수정하면 자동으로 refresh되지 않는다.
당연한 말이지만, 소스코드변경, 저장한것은 도커 안의 파일이 아니라 내컴퓨터 즉, local에서 일어난 것이다.

docker exec -it [컴포넌트id] /bin/bash

이렇게 해서 도커 컴퓨터 내에 들어가서 해당 파일에 수정사항이 반영이 되었는지를 본다면 확실히 알 수 있다.

해당 폴더, cat index.js 라고하면 index.js의 소스코드를 볼 수 있다.

그럼 둘의 동기화가 필요하다는 말인데 어떻게 동기화 시킬 수 있을까?

volumes

둘의 동기화를 위해 필요한 옵션이 바로 volumes이다.

이 옵션을 사용하게되면 내 컴퓨터의 소스코드와, 도커 안의 소스코드를 일치시켜준다.

=> 내 컴퓨터 안에서 소스코드 변경이 있다면 자동으로 도커 안으로 들어가게되고, 도커 안에서 파일을 만들게 되면 그 파일도 자동으로 내컴퓨터로 들어가게된다. (동기화 이루어짐)

# 도커 컴포즈 몇 버전에서 할 것인지
version: "3.7"

# services에는 그룹핑할 컴퓨터들 이름을 적어주면됨. mongoDB컴퓨터와 node컴퓨터 두대를 그룹핑할 것이기에
# 두 컴퓨터의 이름을 원하는대로 적고
services:
  backend:
    #  도커파일을 각 컴퓨터에 넣어 build해야함. 이 build안에는 두가지 명령어를 적어줄 수 있음.
    build:
      # dockerfile에 적어준 도커파일의 위치 (' .'은 현 위치를 말함.)
      context: .
      # 여기 넣을 도커파일이름
      dockerfile: Dockerfile
    # 현위치 index.js의 변경이 있을 경우에 docker안에 myfolder에 있는 index.js와 동기화 시켜줘
    # 내컴퓨터:도커컴퓨터
    volumes:
      - ./index.js:/myfolder/index.js
      - ./email.js:/myfolder/email.js
    #   이렇게 파일 하나씩 넘길수도 있는데, 폴더 하나에 넣고 그 폴더를 통으로 넣어줄 수도 있다.

    # 포트포워딩을 할 경우 포스트맨이나 브라우저 3000번 => 도커 backend로
    ports:
      - 3000:3000
  database-mongo:
    image: mongo:5
    ports:
     - 27017:27017
 # 현위치 index.js의 변경이 있을 경우에 docker안에 myfolder에 있는 index.js와 동기화 시켜줘
    # 내컴퓨터:도커컴퓨터
    volumes:
      - ./index.js:/myfolder/index.js
      - ./email.js:/myfolder/email.js
    #   이렇게 파일 하나씩 넘길수도 있는데, 폴더 하나에 넣고 그 폴더를 통으로 넣어줄 수도 있다.

이렇게 volumes에 적어주면 된다.
이렇게 내 컴퓨터의 index.js가 바뀔때마다 도커의 myforder안의 index.js도 바뀌게 동기화를 시켜주고,
build, up을 하여 빌드하고 실행시켜주고 ,
index.js의 소스코드를 약간 수정하여 저장하면 다시 refresh가 되는것이 확인된다.

자동 refresh가 되기 위해 필요했던것은 volumes와 nodemon이다.
volumes만 있다고 refresh가 되는것은 아니다.!!!
nodemon이 자동 refresh를 시켜주었던 아이이고, 얘는 도커에서 실행한 상태에서 내컴퓨터의 소스코드를 변경시에 도커에도 반영되게하여 nodemon이 작동되게 하려면 이때 volumes옵션이 필요한 것이다!!!

0개의 댓글