🐳 도커와 쿠버네티스

섹션 5: Docker로 다중 컨테이너 애플리케이션 구축하기

락꿈사 2022. 7. 13. 18:58

Target 앱 & 설정

  • 3가지 빌딩 블록과 컨디션
    1. MongoDB Datebase
      • MongoDB 컨테이너를 제거했다가 다시 생성해도 데이터가 손실되지 않아야 함
      • 액세스를 제한할 수 있어야 함(공식 Mongo 이미지를 사용하여 컨테이너에서 생성된 데이터베이스에 사용자와 비밀번호를 추가)
    2. NodeJS REST API Backend Application
      • 백엔드 컨테이너를 제거했다가 다시 생성해도 log 데이터가 손실되지 않아야 함
      • 소스 코드 변경 사항이 즉시 반영되어야 함
    3. React Frontend
      • 소스 코드 변경 사항이 즉시 반영되어야 함
  • 백엔드는 데이터를 저장하고 가져오기 위해 데이터베이스와 통신함
  • 프론트엔드는 백엔드와 통신함

 

 

MongoDB 서비스 도커화 하기

  • MongoDB 컨테이너 실행
    • --name mongodb: 컨테이너명 mongodb로 지정
    • --rm: 중지되면 자동으로 컨테이너 삭제
    • -d: 백그라운드에서 실행
    • -p: 로컬 호스트의 포트 27017과 컨테이너 포트 27017을 노출시켜 연결
$ docker run --name mongodb --rm -d -p 27017:27017 mongo

 

 

Node 앱 도커화 하기

  • 백엔드 Dockerfile 파일 작성
# Docker Hub의 node를 기본 이미지로 사용
FROM node

# 컨테이너의 작업 디렉토리를 /app으로 설정
WORKDIR /app

# package.json을 읽어서 설치할 모듈을 추출
COPY package.json .

# 이 프로젝트의 요구 종속성 설치
RUN npm install

# 나머지 코드를 컨테이너의 작업 디렉토리에 복사
COPY . .

# 80포트 노출
EXPOSE 80

# 컨테이너가 시작될 때 실행되어야 하는 명령어 지정
# node 런타임으로 app.js를 실행
CMD ["node", "app.js"]
  • 이미지 빌드
    • -t 이미지 이름: 이미지의 이름을 goals-node로 지정
$ docker build -t goals-node .

  • 노드 컨테이너 실행
$ docker run --name goals-backend --rm goals-node
  • 결과
    • MongoDB에 연결하지 못해 충돌이 일어남
    • 호스트 머신의 MongoDB 컨테이너가 아니라 동일한 백엔드 컨테이너 내부의 포트에서 MongoDB접근하려고 했기 때문

  • 코드 수정 후 리빌드 후 재실행

  • 프론트앤드 어플리케이션과 통신하기 위해서 중지 후 포트를 노출하여 재실행
$ docker run --name goals-backend --rm -d -p 80:80 goals-node

 

 

React SPA를 컨테이너로 옮기기

  • 프론트앤드 프로젝트에 Dockerfile 작성
FROM node

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 3000

# 컨테이너가 시작될 때 실행되어야 하는 명령어 지정
# package.json의 start 스크랩트를 실행
CMD ["npm", "start"]
  • 이미지 빌드
$ docker build -t goals-react .

  •  리액트 컨테이너 실행
$ docker run --name goals-frontend --rm -d -p 3000:3000 goals-react

  • 결과
    • 에러남
    • 인터렉티브 모드로 실행하지 않았으므로, 입력을 수신하지 않으면 서버가 중지되기 때문

  • -it 옵션을 주어 재실행
    • -it: 인터렉티브 모드로 실행
$ docker run --name goals-frontend --rm -d -p 3000:3000 -it goals-react

  • 결과

 

 

효율적인 컨테이너 간 통신을 위한 Docker 네트워크 추가하기

  • 네트워크 생성
$ docker network create goals-net

  • MongoDB 컨테이너를 생성한 네트워크에 포함하여 실행
$ docker run --name mongodb --rm -d --network goals-net mongo

  • 동일한 네트워크 내의 MongoDB 컨테이너를 찾기 위해 코드 수정후 노드 컨테이너 재실행

  • 동일한 네트워크 내의 MongoDB 컨테이너를 찾기 위해 코드 수정 후 리액트 컨테이너 재실행

  • 결과
    • 오류가 생김
    • 서버가 아닌 브라우저에서 실행되는 애플리케이션이기 때문에 발생한 문제
    • 리액트 코드는 컨테이너 내부에서 실행되는 것이 아니라 항상 브라우저에서 실행되는데, 위에서 작성한 "http://goals-backend/goals"를 컨테이너는 알지만, 브라우저는 알지 못함

  • 리액트 코드 localhost로 재수정후 재빌드

  • localhost에서 백엔드 엔드 포인트에 도달할 수 있도록 노드 애플리케이션을 80포트를 노출하여 재실행 후 리액트 애플리케이션 재실행

  • 결과

 

 

볼륨으로 MongoDB에 데이터 지속성 추가하기

  • MongoDB 컨테이너에 명명볼륨 사용
    • -v 명명볼륨명:컨테이너 내부 저장공간 위치: data라는 명명볼륨과 /data/db를 연결
    • MongDB 컨테이너 내부에 데이터를 저장하는 곳인 "/data/db" 폴더와 호스트 컴퓨터 상의 볼륨(어디에 있는지는 모름) "data"를 매핑함
$ docker run --name mongodb -v data:/data/db --rm -d --network goals-net mongo

  • 결과
    • 컨테이너를 재시작 해도 데이터가 남아 있는 것을 확인할 수 있음

  • 환경변수를 사용하여 데이터베이스에 액세스 하는 컨테이너에 사용자 이름과 비밀번호를 지정하여 컨테이너 재실행
$ docker run --name mongodb --rm -v data:/data/db -d --network goals-net -e MONGO_INITDB_ROOT_USERNAME=max -e MONGO_INITDB_ROOT_PASSWORD=secret mongo

  • 결과
    • 오류남 
    • mogodb와 통신하는 노드 어플리케이션이 이름과 비밀번호 없이 접근하려고 했기에 실패

  • 노드 어플리케이션 코드 수정 후 재빌드 후 재실행
    • name:password@mongodb~

  • 노드 어플리케이션 코드 수정 후 재빌드 후 재실행
    • ?authSource=admin

  • 결과
    • 강의에서는 되다고 했는데 나는 안됨;

 

 

NodeJS 컨테이너의 볼륨, 바인딩 마운트 및 폴리싱(Polishing)

  • 노드 컨테이너에 명명볼륨 사용
    • -v 명명볼륨명:컨테이너 내부 저장공간 위치: logs라는 명명볼륨과 /app/logs를 연결
    • 노드 컨테이너 내부에 데이터를 저장하는 곳인 "/app/logs" 폴더와 호스트 컴퓨터 상의 볼륨(어디에 있는지는 모름) "logs"를 매핑함
  • 노드 컨테이너에 바인드 마운트 설정
    • - v 바인드 마운트 할 로컬 컴퓨터 저장소:컨테이너 내부 경로
    • 현재 프로젝트 위치인 /Users/roxyyujin/Docker & Kubernetes/multi-01-starting-setup/backend를 컨테이너의 /app 폴더와 바인드 마운트 함
  • 노트 컨테이너에 의존성 모듈은 덮어쓰지 않는다고 알림
    • -v 의존성 모듈 위치
    • 컨테이너에 의존성 모듈이 위치하고 있는 /app/node_modules 부분은 그대로 있어야 한다고 컨테이너에 알림
$ docker run --name goals-backend -v "/Users/roxyyujin/Docker & Kubernetes/multi-01-starting-setup/backend:/app" -v logs:/app/logs -v /app/node_modules -d --rm -p 80:80 --network goals-net goals-node

  • 결과

  • 코드가 수정될 때 마다 다시 시작하기 위해서 코드 수정
    • package.json
    • Dockerfile

FROM node:14-alpine3.11

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 80

# 컨테이너가 시작될 때 실행되어야 하는 명령어 지정
# npm 런타임으로 start script를 실행
CMD ["npm", "start"]
  • 중지 후 재시작

  • 결과

  • .dockerignore 파일 작성
node_modules
Dockerfile
.git

 

 

 (바인드 마운트로) React 컨테이너에 대한 라이브 소스 코드 업데이트하기

  • 리액트 컨테이너에 바인드 마운트 설정