이전에 기본 설정인 bridge 모드와 host 모드 그리고 null 모드까지 모두 봤어요.
그런데 어떠한 필요에 의해서 컨테이너의 서비스들이 같은 IP를 써야 하는 경우가 있을 수 있어요. 그럴 때는 어떻게 해야 할까요? 간단한지는 잘 모르겠지만 컨테이너 하나에 2개의 서비스를 넣는 방법이 있을 수 있겠네요. 하지만 이런 방법은 무슨무슨 법 위반이래요.
이럴 때 사용할 수 있는 좋은 방법이 있는데 바로 IP를 공유하는 거예요.
시간 날 때 그림을 그려서 올려보도록 할게요. 우선은 설명하자면
- 도커가 컨테이너를 생성하면서 그 컨테이너를 위한 네트워크 네임스페이스를 생성하고 가상 인터페이스도 만들어서 그 인터페이스에 IP도 할당해요.
- 서비스 1이 돌아가는 컨테이너를 만들면서 네트워크를 bridge도 아니고 host도 아니고 null도 아닌 1에서 만든 컨테이너의 네트워크를 할당해줘요. 붙여준다고 이야기하는 게 더 좋을까요?
- 또 다른 서비스 2가 돌아가는 컨테이너를 만들면서 아까 1번에서 만들었던 컨테이너의 네트워크를 또 붙여줘요.
- 끝.
설명이 길면 지루하니까 바로 볼게요.
➜ ~ docker container run -d -it --name containerofcontainer alpine
ed6836c9dc8c4c535df2114c22d3ee92d8721e181994b950408984f536bcda7d
➜ ~ docker exec containerofcontainer ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
120: eth0@if121: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
➜ ~ docker container run -d -it --network container:containerofcontainer nginx:1.14
8d90959f158020af2b1f15799015ecf2640c5fbf9d9dc3fcc0de644b5cb5ab34
➜ ~ curl 172.17.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
➜ ~ docker container run -d -it --network container:containerofcontainer xodwkx2/show-me-host:2.0.0
bed64aa02a3d5e864d4ef8da9a11cda328655145e6614ee5a00560c9b3c77385
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bed64aa02a3d xodwkx2/show-me-host:2.0.0 "docker-entrypoint.s…" 3 seconds ago Up 3 seconds peaceful_bhaskara
8d90959f1580 nginx:1.14 "nginx -g 'daemon of…" About a minute ago Up About a minute interesting_kare
ed6836c9dc8c alpine "/bin/sh" 8 minutes ago Up 8 minutes containerofcontainer
➜ ~ curl 172.17.0.2:8080
Your app is running on Host: ed6836c9dc8c
alpine 이미지를 사용해서 첫 번째 컨테이너를 bridge 네트워크 모드로 하나 생성했어요. 이름은 컨테이너의 컨테이너라는 의미로 containerofcontainer라고 지어봤어요. 그리고 IP를 확인해보니 172.17.0.2/16으로 나오네요.
그리고 바로 이름은 따로 주지 않고 nginx:1.14 이미지로 두 번째 컨테이너를 생성했어요. 이때 네트워크 옵션을
--network container:containerofcontainer라고 줬어요. 포트는 따로 개제하지 않고 생성했어요. 그러면 컨테이너의 IP:PORT 조합으로만 접속할 수 있겠죠? 아이피 확인 없이 믿음으로 바로 172.17.0.2(:80)로 curl 명령을 날려봤어요.
예상대로 Welcome to nginx!라는 반가운 메시지가 떴어요.
이번에는 너의-호스트-이름을-보여줘:2.0.0 이미지를 사용해서 세 번째 컨테이너를 생성했어요 마찬가지로 네트워크는 컨테이너의 컨테이너 컨테이너 네트워크를 붙여줬어요. 이 이미지는 8080 포트를 기본으로 열고 서비스하는 nodejs 애플리케이션이 돌아가고 있어요. 그래서 alpine 컨테이너의 8080 포트로 curl 명령을 때려봤어요.
여기서 돌아오는 대답이 ed6836.. 너의-호스트-이름을-보여줘:2.0.0 컨테이너의 ID가 아니라 컨테이너의 컨테이너 컨테이너 ID가 나왔어요. 그래서 한번 확인해봤어요.
➜ ~ docker exec bed64aa02a3d hostname
ed6836c9dc8c
그리고 하나 더 너의-호스트-이름을-보여줘:2.0.0 컨테이너에서 curl localhost(:80)을 해봤어요. 그리고 8080은 당연히 될 거구요. 내친김에 어떤 포트들이 열려있는지 확인해봤습니다. 그리고 nginx 컨테이너에서도 어떤 포트들이 열려있는지 확인해봤어요. 각각 컨테이너에서 오픈된 포트는 모두 보여주면서 다른 컨테이너에서 실행되고 있는 프로세스의 ID는 - 로 나오는 게 인상 깊었어요.
root@ed6836c9dc8c:/usr/src/app# curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
root@ed6836c9dc8c:/usr/src/app# curl localhost:8080
Your app is running on Host: ed6836c9dc8c
root@ed6836c9dc8c:/usr/src/app# netstat -nlpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1/node
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
# netstat -nlpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginx: master pro
이렇게 쓰는 데가 도대체 어디 있냐구요?
그 건 쿠버네티스 파드에 대해서 파헤쳐볼 때 마저 이야기해보도록 하지요.
끝!