🐳 도커와 쿠버네티스
섹션 5: Docker로 다중 컨테이너 애플리케이션 구축하기
락꿈사
2022. 7. 13. 18:58
Target 앱 & 설정

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