본문 바로가기
[DevOps]/Docker

Docker로 다중 컨테이너 애플리케이션 구축하기 - 1 (여러 개의 컨테이너 만들기)

by 황원용 2023. 7. 7.
728x90

  • 이번 실습에서는 웹 애플리케이션 실행에 필요한 3가지 기본 요소인 서버, 클라이언트, 데이터베이스를 도커로 컨테이너 화하여 컨테이너로 실행시키는 것이 목표이다.
  • 실습에 사용할 폴더에는 Node.js 기반의 백엔드 API 서버와 리액트 기반의 프론트 클라이언트 파일이 들어있다.
  • 데이터베이스로는 mongoDB를 사용할 것이다.
  • 노드와 리액트, mongoDB를 몰라도 어떤 흐름으로 컨테이너 간 통신이 이뤄지는지 이해할 수 있도록 간략하게 설명하겠다.
  • 기본적인 도커 명령어 정도는 숙지하고 있어야 이해가 빠를 것이다.

 

 

로컬 호스트 머신(백엔드 서버)과 도커 컨테이너(데이터베이스 서버) 연결해보기

백엔드 서버의 app.js

  • app.js 파일 안에는 mongoDB와 연결하기 위한 로컬호스트의 포트번호가 적혀있다.
  • 포트번호는 27017이다.

 

 

docker hub 내 mongoDB 공식 이미지

 

 

mongoDB 이미지 빌드 & 컨테이너 실행

docker run --name mongodb --rm -d -p 27017:27017 mongo

  • docker build -t mongodb mongo 명령어로 mongoDB에서 제공하는 공식 이미지를 빌드한다.
  • 위의 정보를 토대로 살펴보면 nodejs 서버는 mongoDB와 27017 포트로 통신하려고 한다.(app.js)
  • mongoDB 공식 이미지로 생성한 컨테이너의 mongoDB는 기본적으로 27017 포트로 듣고 있다.
  • 따라서 docker run --name mongodb --rm -d -p 27017:27017 mongo 명령어로 도커 컨테이너의 27017 포트를 열어준다.
    • 로컬호스트의 27017 포트를 도커 컨테이너의 27017과 연결시켜 도커 컨테이너 내부의 mongoDB가 들을 수 있게 하는 것이다.
    • mongoDB는 기본적으로 27017을 듣고 있기 때문에 컨테이너의 27017 포트를 열어 외부에서 컨테이너 내부의 mongoDB까지 통신이 올 수 있도록 한다.

 

백엔드 서버 실행

  • 노드 서버를 실행하면 정상적으로 mongoDB와 연결되었음 확인할 수 있다.
  • 현재는 3가지 중에 데이터베이스 서버만 도커화가 진행되었다.
  • 이는 그저 맛보기였을 뿐...
  • 본격적으로 백엔드 서버와 클라이언트도 도커 컨테이너로 실행해 보자.

 

 

백엔드 서버 컨테이너 만들기

  • 노드 서버 폴더 안에 Dockerfile을 생성하고 이미지를 빌드할 정보를 입력한다.

 

docker build -t goals-node .

  • 이미지를 빌드한다.

 

docker run --name goals-backend --rm goals-node

  • 이대로 컨테이너를 실행하면 mongoDB와 연결이 실패했다는 에러가 발생한다. 왜일까?

 

 

  • 백엔드 서버 app.js의 mongoDB와 연결을 설정하는 부분이 localhost인 채로 빌드됐기 때문이다.
  • 노드 서버가 데이터베이스를 찾으려고 하는데 주소를 localhost로 설정하는 바람에 자신의 컨테이너에서 찾고 있으니 에러가 난 것이다.
  • mongoDB는 mongoDB만의 컨테이너에 있다.

 

  • localhost 대신 host.docker.internal을 입력하면 도커가 알아서 mongoDB 컨테이너를 찾아 연결한다.

 

  • 이미지를 재빌드하고

 

  • docker run 명령으로 컨테이너를 실행하면 백엔드 서버 컨테이너가 도커 컨테이너와 연결된다.
  • 포트는 80:80을 열어주었다.

 

 

리액트 클라이언트 컨테이너 만들기

  • 리액트 클라이언트에도 Dockerfile을 만든다.

 

docker build -t goals-react .

  • 도커 이미지를 빌드한다.

 

docker run --name goals-frontend --rm -d -p 3000:3000 -it goals-react

  • 3000:3000 포트를 열어준다.
  • -it로 인터렉티브 쉘 모드로 실행해줘야 한다.
  • 웹페이지의 입력창에 값을 넣는 상호작용을 위해 -it를 붙여줘야 한다.
    • -it를 붙이지 않으면 에러가 난다.
    • 상호작용을 하지 않더라도 리액트를 실행하기 위해 기본적으로 필요한 플래그인 것 같다.

 

 

정리

  • 지금까지의 내용을 간단히 정리해 보자.
  • 맨 처음에는 MongDB만 컨테이너화를 진행하고, node 서버는 로컬 호스트 머신에서 실행했다.
    • 로컬 호스트 머신과 컨테이너 간의 통신을 실습했다.
  • 이후에는 node와 React를 컨테이너 화하면서 현재는 3개의 빌딩 블록이 모두 컨테이너로 실행되고 있다.
    • 현재는 세 컨테이너 간의 통신이 이뤄지고 있지 않다.
    • 백엔드 서버와 데이터베이스 컨테이너만이 통신하고 있을 뿐이다.
    • 리액트는 완전히 별도의 컨테이너에서 독립적으로 돌아가고 있다.

 

 

개성해야 할 사항

  1. 3 개의 컨테이너가 서로 통신하고 있지 않다.
  2. 컨테이너 간 통신에 코드 수정이 들어가 비효율적이다.(localhost -> host.docker.internal)
  3. 컨테이너가 삭제되면 데이터베이스의 데이터가 모두 날아간다.
  • 이제 컨테이너 간의 통신을 하나의 네트워크로 연결하고 컨테이너가 삭제돼도 데이터는 지속되게 바꿔보자.

 

 

 

참고

Udemy - Docker & Kubernetes : 실전 가이드

728x90