# 네트워킹: 컨테이너 통신

# 컨테이너와 통신

컨테이너도 컨테이너 외부와 통신이 가능한데 통신하는 대상으로 이를 구분하자면 크게 세 가지 케이스가 있다.

## WWW 통신

컨테이너는 기본적으로 WWW(World Wide Web)에 요청을 보낼 수 있다. 따라서 컨테이너 내부의 도커화 된 애플리케이션은 컨테이너 외부의 웹에 request를 전송하는 것이 가능하다.

컨테이너라고 별 다른 설정이 필요하지는 않고 애플리케이션 내부에 외부 WWW로 request를 보내는 코드가 있으면 작동한다.

## 컨테이너-로컬 호스트 통신

컨테이너는 호스트 머신의 서비스와도 통신할 수 있다.

이것도 크게 복잡할 것은 없으나 컨테이너 내부에서 [localhost](http://localhost)를 사용하려 하면 호스트 머신이 아니라 컨테이너 내부의 [localhost](http://localhost)로 인식하기 때문에

```txt
localhost:3000
```

이었다면

```txt
host.docker.internal:3000
```

으로 교체해주면 된다.

`host.docker.internal`를 사용하게 되면 도커에 의해 호스트 머신의 IP주소로 변환된다.

예를 들면

호스트 머신의 MongoDB를 사용하기 위해

```js
mongoose.connect(
  'mongodb://localhost:27017/swfavorites',
  { useNewUrlParser: true },
  (err) => {
    if (err) {
      console.log(err);
    } else {
      app.listen(3000);
    }
  }
```

이러한 코드가 포함된 애플리케이션의 이미지를 빌드하고 컨테이너에서 돌리려고 하면 정상적으로 작동하지 않는다.

```js
mongoose.connect(
  'mongodb://host.docker.internal:27017/swfavorites',
  { useNewUrlParser: true },
  (err) => {
    if (err) {
      console.log(err);
    } else {
      app.listen(3000);
    }
  }
```

로 바꿔주면 호스트 머신의 몽고DB를 사용 가능하다.

당연하겠지만 애초에 컨테이너 내부에 있는 DB가 아니기 때문에 컨테이너를 삭제해도 데이터는 날아가지 않는다.

## 컨테이너-컨테이너 간 통신

컨테이너는 또 다른 컨테이너와도 통신할 수 있다. 위에서는 로컬의 몽고DB와 통신했으나 몽고DB가 돌고 있는 컨테이너와 애플리케이션 컨테이너를 연결할 수 있다.

몽고DB 이미지는 도커허브에서 이미 제공되고 있으므로 별다른 도커파일 작성 없이

```bash
docker run mongo
```

를 실행하면 몽고DB를 가진 컨테이너를 돌리게 된다.

따라서 몽고DB 컨테이너를 detached 모드로 다시 돌려보면

```bash
docker run -d --name mongodb mongo                                 ─╯
cbce28bf42f3516a50e3287d15280c49272dff34c72f7d12ee174f0b92d42ca4
```

이런 식으로 생성된다.

이제 로컬의 몽고DB에서 몽고DB 컨테이너의 몽고DB로 연결해야 하는데

```sh
docker container inspect mongodb
```

명령어를 이용해 컨테이너를 검사하면 정보들이 출력되는데 내리다보면 `IPaddress`를 발견할 수 있다.

발견한 IPaddress를

```js
mongodb://IPaddress:27017/swfavorites
```

에 집어넣어주면 컨테이너의 몽고DB와 통신할 수 있게 된다.

### Docker Network

컨테이너끼리 통신하는 데 위처럼 주소를 그냥 하드코딩해도 돌아는 가겠지만 또 다른 방법이 있다.

```sh
docker run --network my_network
```

`--network`옵션을 붙여주면 여러 컨테이너를 한 네트워크 안에 묶어버릴 수 있다.

![](https://i.imgur.com/AmqkxIg.png align="left")

그림으로 보자면 위와 같은 느낌이다. 컨테이너들을 기능별로 분리할 수 있으면서도 통신이 원활하다면 상당히 바람직한 상황일 것이다.

그러면 도커 네트워크를 이용하는 컨테이너를 돌리기 위해

```bash
docker run -d --name mongodb --network favorites-net mongo                                                                                     ─╯
90ed02f4da3372b12429598fc1d9e6604e162d23bb8cf15d523c248fa3b594d9
docker: Error response from daemon: network favorites-net not found
```

를 시도하면 네트워크를 찾을 수 없다는 에러가 나온다.

네트워크는 자동적으로 생성되지 않기 때문에

```sh
docker network create favorites-net
```

네트워크를 만들어주면 된다.

네트워크를 만든 후 위 명령어를 다시 실행해주면

```bash
docker run -d --name mongodb --network favorites-net mongo                                                                                     ─╯
b4b5344edb4da69500e4a0d50138e4c85c50dc88e95e66194288930fc3f6dce7
```

성공적으로 진행된 것을 알 수 있다.

아까 네트워크를 사용하면 주소를 하드코딩하지 않아도 된다고 하였다. 그럼

```js
mongodb://IPaddress:27017/swfavorites
```

이 부분도 그대로 적을 필요가 없다는 말이 되겠다. 여기에는

```js
mongodb://컨테이너이름:27017/swfavorites
```

통신하는 컨테이너 이름을 적어주면 된다.

내부적으로는 도커가 컨테이너 이름을 받아 컨테이너의 IP주소로 변환하는 과정이 이루어지기 때문에 통신이 가능하다.

그러면 다시 애플리케이션 컨테이너를 만들어서 돌려볼 차례다. 같은 네트워크에 넣어줘야하기 때문에

```sh
docker run --name favorites --network favorites-net -d --rm -p 3000:3000 favorites-node                                                        ─╯
c2e2d4059cb3053f24aef257973a61c5bec157a94d032d9861f88ccf5c3dde23
```

똑같이 `--network` 옵션에 같은 네트워크를 설정해준다.
