관리 메뉴

코딩하는 락커

섹션4: 네트워킹: (교차) 컨테이너 통신 본문

🐳 도커와 쿠버네티스

섹션4: 네트워킹: (교차) 컨테이너 통신

락꿈사 2022. 7. 6. 17:42

case 1: WWW 통신 컨테이너

  • 애플리케이션이 포함된 컨테이너가 하나 있다고 가정
  • 애플리케이션은 웹 API를 통해 다른 WWW 사이트와 통신할 수 있음 (ex. 위 그림과 같이 GET HTTP 요청을 some-api.com/ API에 보낼 수 있음)
  • 즉, 컨테이너 내부의 도커화 된 앱은 컨테이너 외부의 웹사이트/웹페이지에 request를 전송할 수 있음

 

 

case 2: 컨테이너에서 로컬 호스트 머신으로의 통신

  • 애플리케이션이 포함된 컨테이너는 호스트 컴퓨터에서 실행중인 특정 서비스와 통신할 수 있음 (ex. 위 그림과 같이 도커 없이 호스트 컴퓨터에서 돌아가고 있는 데이터베이스와 통신할 수 있음)
  • 즉, 컨테이너 내부의 도커화 된 앱은 컨테이너 외부의 호스트 컴퓨터와 통신할 수 있음

 

 

case 3: 컨테이너 간 통신

  • 애플리케이션이 포함된 컨테이너는 다른 컨테이너에서 실행중인 특정 서비스와 통신할 수 있음 (ex. 위 그림과 같이 로컬 컴퓨터에서 도커를 통해 돌아가고 있는 SQL 데이터베이스와 통신할 수 있음)
  • 도커 컨테이너를 사용하면 한 가지 주요 작업만 수행하는 것이 강력히 권장되며, 그것이 모범사례임
  • 즉, 컨테이너 내부의 도커화 된 앱은 호스트의 다른 컨테이너와 통신할 수 있음

 

 

컨테이너 만들기 & 웹 통신하기(WWW)

  • Dockerfile
FROM node

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

CMD ["node", "app.js"]
  • 빌드 
$ docker build --platform amd64 -t favorites-node .

  • 컨테이너 실행 (detached mode로)
$ docker run --name favorites -d --rm -p 3000:3000 favorites-node

  • 결과
    • 컨테이너가 존재하지 않음

  • 컨테이너 실행 (attached mode로)
$ docker run --name favorites --rm -p 3000:3000 favorites-node

  • 결과
    • MongoNetworkError발생
    • 호스트 컴퓨터에 연결하지 못함
    • 현재 코드와 같이 localhost를 사용하여 호스트 컴퓨터에 연결하는 것은 실패한다는 것을 알 수 있음

  • HTTP 요청 테스트를 위해 코드 수정
    • MongoDB 데이터베이스에 연결하지 않고 웹 서버를 가동하는 것만으로 컨테이너를 실행함

  • 재빌드 후 실행 결과
    • 컨테이너가 계속 실행되는 것을 확인할 수 있음
    • 데이터베이스에 연결하는 /favorite 엔드포인트는 작동하지 않음
    • 그러나 그 외에 /movies, /people 엔드포인트는 제대로 작동함

  • 즉, 기본적으로 컨테이너는 특별한 설정 없이 월드 와이드 웹에 요청을 보낼 수 있음

 

 

호스트 통신 작업을 위한 컨테이너 만들기

  • 현재 노드 어플리케이션은 컨테이너에 존재함
  • 현재 MongoDB는 로컬 머신에 설치되어 실행중임
  • 코드 수정 (app.js)
mongoose.connect(
  // 원래 코드
  // 'mongodb://localhost:27017/swfavorites',

  // docker.internal: localhost를 도커가 이해할 수 있는 특별한 도메인
  // 도커 컨테이너 내부에서 알 수 있는 호스트 컴퓨터의 IP주소로 변환됨
  // 만약 호스트 컴퓨터에 실행중인 웹 서버가 있다면 http://docker.internal:3000/ 등으로도 접속 가능
  'mongodb://host.docker.internal:27017/swfavorites',
  { useNewUrlParser: true },
  (err) => {
    if (err) {
      console.log(err);
    } else {
      app.listen(3000);
    }
  }
);
  • 리빌드 후 컨테이너 재실행

  • 결과
    • GET localhost:3000/favorites을 요청했을 경우 정상 작동하는 것을 볼 수 있음
    • 이 데이터베이스는 현재 컨테이너에서 실행되지 않고 호스트 컴퓨터에서 실행되고 있음

  • 즉, 컨테이너는 docker.internal URL을 사용하면 호스트 컴퓨터와 통신할 수 있음

 

 

컨테이너 간 통신: 기본 솔루션

  • Mongodb 컨테이너 가동
    • docker hub에 있는 mongodb 이미지를 사용
$ docker run -d --name mongodb mongo

  • 방금 시작한 mongodb 컨테이너 조사
    • 컨테이너의 IP 주소를 알아낼 수 있음
$ docker container inspect mongodb

  • 코드 수정
mongoose.connect(
  // 원래 코드
  // 'mongodb://localhost:27017/swfavorites',
  
  // 다른 컨테이너에서 실행중인 mongodb의 주소를 넣어줌
  'mongodb://172.17.0.2l:27017/swfavorites',
  { useNewUrlParser: true },
  (err) => {
    if (err) {
      console.log(err);
    } else {
      app.listen(3000);
    }
  }
);
  • 리빌드 후 재실행
    • 두개의 컨테이너가 돌게 됨

  • 결과
    • GET localhost:3000/favorites을 요청했을 경우 완전히 새로운 데이터베이스에 액세스한 것을 알 수 있음
    • 즉 로컬 호스트 컴퓨터의 mongodb가 아닌 컨테이너에서 실행된 데이터베이스에 액세스 했음

 

 

Docker Networks 소개: 우아한 컨테이너 간 통신

  • 도커로 컨테이너 네트워크를 만들 수 있음
  • 네트워크란 다중 컨테이너가 있을 때 컨테이너간의 통신을 허용하는 것을 의미함
  • 다중 컨테이너를 하나의 동일한 네트워크에 밀어넣을 수 있는 명령어
$ docker run --network {네트워크_이름}
  • 도커 네트워크 생성
    • 도커 네트워크는 도커 내부 네트워크이며 컨테이너 간에 서로 통신하게 하는데 사용할 수 있음
$ docker network create favorites-net

  • mongodb 컨테이너를 방금 생성한 네트워크에 포함하여 재실행

  • 코드 수정
    • 다른 도커 컨테이너의 이름이 도커에 의해 그 컨테이너의 IP로 변환됨
mongoose.connect(
  // 원래 코드
  // 'mongodb://localhost:27017/swfavorites',

  // 동일한 네트워크 내에서 실행중인 mongodb 컨테이너의 이름을 넣어줌
  'mongodb://mongodb:27017/swfavorites',

  { useNewUrlParser: true },
  (err) => {
    if (err) {
      console.log(err);
    } else {
      app.listen(3000);
    }
  }
);
  • 리빌드 후 방금 생성한 네트워크에 포함하여 재실행

  • 결과
    • GET localhost:3000/favorites을 요청했을 경우 완전히 새로운 데이터베이스에 액세스한 것을 알 수 있음
    • 즉 로컬 호스트 컴퓨터의 mongodb가 아닌 같은 네트워크에서 실행중인 컨테이너의 데이터베이스에 액세스 했음
    • 또한, 지금과 같이 어떤 컨테이너와 동일한 네트워크 내에서 연결하는 컨테이너가 하나만 존재할 경우 포트를 노출할 필요가 없음 (포트 노출은 로컬 호스트 컴퓨터나 컨테이너 외부에서 컨테이너에 연결하려고 하는 경우만 필요함)

 

 

Docker가 IP 주소를 해결하는 방법

  • 도커는 소스 코드를 읽어서 IP 주소를 대체하는 것이 아님
  • 도커는 애플리케이션이 실행되는 환경을 소유하고, 애플리케이션이 HTTP 요청이나 MongoDB 요청 또는 컨테이너에서 다른 종류의 요청을 보내는 경우에 이를 인식함
  • 그리고 그 시점에서 도커는 주소, 컨테이너 이름, host.docker.internal을 실제 IP 주소로 변경함
Comments