Post

docker 관련 메모

시작

image

컨테이너 간 통신

한줄요약

  • 기본 설정대로라면,
    • 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 가 서로 통신을 하는 경우

image

가상 IP 를 부여받는 경우,

image

TCP/IP 통신을 하는 것 처럼, 중간에 복잡한 네트워크 처리 과정을 거쳐야한다. 🫠

Container Communication

image

가상(= 논리적)의 네트워크 시스템을 구축하는데, 가상의 gateway 를 만들어서 컨테이너 간 통신을 가능하게 한다.

Hostgateway 와 통신을 주고 받고, 컨테이너 ip 주소는 가상의 주소이기 때문에 IP 주소를 외부로 노출하기 전까지는 직접적인 접근이 불가능하다.

하지만 -p 8080:8080 같은 Port 옵션으로 간단하게 외부에서 가능하도록 설정할 수 있다. 이는 다음과 같은 과정을 거친다.

  • 목적 : 가상의 네트워크 값인 eth0Host 에 알려주어야 한다.
    • 호스트의 Port 에 맵핑시키는 작업이 필요하다.
  • 각 컨테이너가 가지는 eth0 에 대응되는 veth 라는 가상 네트워크 인터페이스를 생성한다.
  • vethbridge 에 존재하는 인터페이스에 바인딩 시킨다.
  • -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 NameIP
mongodb172.17.0.5
mysql172.17.0.6
postgresl172.17.0.7

출처

This post is licensed under CC BY 4.0 by the author.