docker 관련 메모
시작
컨테이너 간 통신
한줄요약
- 기본 설정대로라면,
- bridge 가 gateway 역할을 하며
- 각각 가상의 ip 가 부여된 컨테이너들의 공유기 역할을 한다.
1
2
3
4
5
6
❯ docker network ls
NETWORK ID NAME DRIVER SCOPE
d5bcee467e62 bridge bridge local
896f7842c650 host host local
18d439ef64b4 msa3-parent_default bridge local
13cfbae9cf27 none null local
위 코드에서 주목해야 할 부분은 이 부분이다.
1
2
3
4
5
6
7
8
9
10
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
172.17.0.0/16
라는 말을 통해 무엇을 알 수 있는가?
172.17.0.0
~ 172.17.255.255
사이의 IP 범위(= 65536)를 커버할 수 있다는 의미이다. 실제 IP 가 아니고, 각각의 컨테이너에 부여하는 가상의 IP 이다.
현재 h2 컨테이너가 실행되고 있는데, inspect 옵션으로 살펴보면 많은 정보가 쏟아져 나온다. 그 중에 하단부분을 살펴보면 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
"NetworkSettings": {
"Bridge": "",
"SandboxID": "7bc64597b5e63e242a9a04ad36fa116099d45ac4da10820ec5065e26738debb6",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"1521/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "1521"
}
],
"81/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "81"
}
]
},
"SandboxKey": "/var/run/docker/netns/7bc64597b5e6",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "fb702bc1226b835d44355bc5f44ab9f997170a3ba58f8bcd738d02e33138c03e",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "d5bcee467e62cb743d80a5774ca584abcd039d615b28017c1f983061a9f69c6e",
"EndpointID": "fb702bc1226b835d44355bc5f44ab9f997170a3ba58f8bcd738d02e33138c03e",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
이것도 너무 길다. 좀 더 잘라서 보자.
Ports 정보
1
2
3
4
5
6
7
8
9
10
11
12
13
14
"Ports": {
"1521/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "1521"
}
],
"81/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "81"
}
]
},
Network 정보
1
2
3
4
"EndpointID": "fb702bc1226b835d44355bc5f44ab9f997170a3ba58f8bcd738d02e33138c03e",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"MacAddress": "02:42:ac:11:00:02",
Gateway
, IP 주소
, 그리고 Mac 주소
까지 담겨 있다. 😱
가상 IP
먼저, 동일한 Host
를 가지는 프로세스 A, B 가 서로 통신을 하는 경우
가상 IP 를 부여받는 경우,
TCP/IP
통신을 하는 것 처럼, 중간에 복잡한 네트워크 처리 과정을 거쳐야한다. 🫠
Container Communication
가상(= 논리적)의 네트워크 시스템을 구축하는데, 가상의 gateway
를 만들어서 컨테이너 간 통신을 가능하게 한다.
Host
는 gateway
와 통신을 주고 받고, 컨테이너 ip 주소는 가상의 주소이기 때문에 IP 주소를 외부로 노출하기 전까지는 직접적인 접근이 불가능하다.
하지만 -p 8080:8080
같은 Port
옵션으로 간단하게 외부에서 가능하도록 설정할 수 있다. 이는 다음과 같은 과정을 거친다.
- 목적 : 가상의 네트워크 값인
eth0
를Host
에 알려주어야 한다.- 호스트의
Port
에 맵핑시키는 작업이 필요하다.
- 호스트의
- 각 컨테이너가 가지는
eth0
에 대응되는veth
라는 가상 네트워크 인터페이스를 생성한다. veth
를bridge
에 존재하는 인터페이스에 바인딩 시킨다.-p 8080:8080
Container
의 8080 포트를Host
의 8080 포트에 연결한다.
Bridge 생성하기
default 설정으로 docker0
이라는 bridge
네트워크가 생성된다.
Subnet
:172.17.0.0/16
default 설정 이외에 커스텀 bridge
를 생성할 수 있다.
1
2
3
4
5
docker network create \
--driver=bridge \
--subnet=172.19.0.0/16 \
--gateway=172.19.0.1 \
customBridgeNetwork
이를 컨테이너와 결합시키기 위해서는
1
2
# 이미 구동 중인 컨테이너
docker network connect customBridgeNetwork ${container_name}
1
2
# 구동시킬 때 네트워크에 연결
docker run --network customBridgeNetwork --name ${container_name}
내장 DNS
가상의 IP 가 부여되기 때문에, 통신을 위해서 DNS 가 존재한다.
127.0.0.11
에서 실행되는 Embedded DNS
가 있다.
Container 의 이름, 가상 IP 가 적힌 테이블 형태로 존재한다.
Container Name | IP |
---|---|
mongodb | 172.17.0.5 |
mysql | 172.17.0.6 |
postgresl | 172.17.0.7 |