menuhwang

Docker Bridge 네트워크 튜토리얼 본문

DevOps/Docker

Docker Bridge 네트워크 튜토리얼

menuhwang 2023. 8. 1. 18:09

도커 공식 문서에서 제공하는 Bridge network tutorial을 따라하고 정리한 글입니다.

 

진행 환경

AWS EC2 t3.micro (vCPU : 2, RAM : 1GB)

OS : Ubuntu 22.04

도커 : 24.0.5

 

default bridge network 예제

이 예제에서는 서로 다른 두 개의 alpine 컨테이너를 실행해 몇 가지 테스트를 진행하여 어떻게 서로 통신하는지 이해해 보겠습니다.

 

1. 도커 네트워크 리스트 확인

sudo docker network ls

현재 도커 네트워크 리스트를 확인하는 명령어입니다.

 

네트워크를 따로 추가하지 않았다면, 아래처럼 기본 네트워크인 bridge와 host, none 세 개가 출력됩니다.

$ sudo docker network ls

NETWORK ID     NAME      DRIVER    SCOPE
ba8fb027e7df   bridge    bridge    local
09615e71ca1c   host      host      local
0da62b715df4   none      null      local

 

2. 테스트용 컨테이너 실행

sudo docker run -dit --name alpine1 alpine ash
sudo docker run -dit --name alpine2 alpine ash

--network 옵션을 통해 네트워크 설정을 해주지 않으면 자동으로 bridge 네트워크에 연결됩니다.

 

컨테이너가 잘 실행되었는지 확인해보겠습니다.

sudo docker container ls
$ sudo docker container ls

CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
790984c97fcf   alpine    "ash"     5 minutes ago   Up 5 minutes             alpine2
390f16e36710   alpine    "ash"     5 minutes ago   Up 5 minutes             alpine1

 

정상적으로 두 개의 컨테이너가 실행되었음을 확인했으면, 다음에는 bridge 네트워크 정보를 확인해보도록 하겠습니다.

 

3. bridge 네트워크 정보 확인

sudo docker network inspect bridge
$ sudo docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "ba8fb027e7df950bad008b1d3c61ed4a7b202320480c42e580bb73a9cb944ea6",
        "Created": "2023-08-01T06:04:25.041899309Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "390f16e3671099093a6fa9841c172c7a087ef1189bf8bd0bfc3cdabfbf54a491": {
                "Name": "alpine1",
                "EndpointID": "0282ca86bcdc7db59e59c2aac81bd63a672c0be001e774c5a108d0eb2bc251c1",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "790984c97fcfa8a5ed17b2b70b2681c9824024f36c156a725c4ae0adbd823df8": {
                "Name": "alpine2",
                "EndpointID": "e61441116b395c60eb2fddbef825a56fc4757c6e8530b840ceafc20b1cc49b0f",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

bridge는 172.17.0.1 게이트웨이를 사용하고 있다는 것을 확인할 수 있고, Containers를 보면 각각 172.17.0.2, 172.17.0.3 IP주소를 할당받은 alpine1과 alpine2를 확인할 수 있습니다.

 

4. 통신 테스트

백그라운드에서 돌아가고 있는 컨테이너에 연결해 통신 테스트를 진행해보도록 하겠습니다.

 

alpine1에 연결하기

sudo docker attach alpine1
$ sudo docker attach alpine1
/ #

콘솔 창에 #로 표시되었다면, 컨테이너에 root 유저로 정상적으로 접근했음을 의미합니다.

 

현재 컨테이너의 IP 주소를 확인해보겠습니다.

ip addr show
# ip addr show
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
4: eth0@if5: <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

두 번째 항목을 보면, 앞서 진행한 bridge 네트워크 정보 확인 과정과 같이 172.17.0.2의 IP주소를 확인할 수 있습니다.

 

5. 외부와 통신 테스트

ping 커맨드를 통해 외부와 통신이 정상적인지 확인해보겠습니다.

ping -c 2 google.com
# ping -c 2 google.com
PING google.com (142.250.196.142): 56 data bytes
64 bytes from 142.250.196.142: seq=0 ttl=45 time=32.698 ms
64 bytes from 142.250.196.142: seq=1 ttl=45 time=32.746 ms

--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 32.698/32.722/32.746 ms

 

두 개의 패킷을 정상적으로 받았다면, 성공입니다.

 

6. alpine2 컨테이너와 통신 테스트

위 와 같은 방법으로 이번에는 alpine2 컨테이너와 통신해 보도록 하겠습니다.

 

alpine2의 IP 주소를 통해 ping 테스트를 해보겠습니다.

ping -c 2 172.17.0.3
# ping -c 2 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.126 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.078 ms

--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.078/0.102/0.126 ms

 

이번에는 alpine2 컨테이너 이름 그대로 테스트 해보도록 하겠습니다.

ping -c 2 alpine2
# ping -c 2 alpine2
ping: bad address 'alpine2'

왜 IP주소도, 도메인도 아닌 컨테이너 이름으로 테스트해봤는지 다음 챕터에서 다시 한 번 언급하도록 하겠습니다.

 

7. 컨테이너 접속 종료

CTRL + p, q 를 통해 컨테이너 접속을 종료할 수 있습니다.

(CTRL을 누른 채로 p, q를 순서대로 각각 눌러주세요.)

 

exit 명령어로 접속을 끊을 수 있습니다만, exit은 컨테이너도 함께 종료됨을 유의해주세요.

 

8. 컨테이너 종료 및 삭제

sudo docker stop alpine1 alpine2
sudo docker rm alpine1 alpine2

 

bridge network 생성 예제

이번 예제에서는 alpine 컨테이너를 총 4개 실행하게 됩니다.

두 개는 직접만든 alpine-net 네트워크에 연결하고, 하나는 bridge 네트워크에만, 또 다른 하나는 alpine-net과 bridge 모두 연결해 보겠습니다.

 

1. alpine-net 생성

sudo docker network create --driver bridge alpine-net

--driver 옵션이 없어도 기본적으로 bridge로 설정됩니다만, 튜토리얼이기 때문에 직접 옵션을 추가해보았습니다.

 

2. 네트워크 생성 확인

sudo docker network ls
$ sudo docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
7cd6af8149a4   alpine-net   bridge    local
ba8fb027e7df   bridge       bridge    local
09615e71ca1c   host         host      local
0da62b715df4   none         null      local

이전 튜토리얼과 다르게 직접 생성한 alpine-net을 확인 할 수 있습니다.

 

alpine-net에 대한 자세한 정보도 조회해 보겠습니다.

sudo docker network inspect alpine-net
$ sudo docker network inspect alpine-net
[
    {
        "Name": "alpine-net",
        "Id": "7cd6af8149a45f3c645a6edabb9461cd071a4d73e410182df72a464914bd1f55",
        "Created": "2023-08-01T08:00:40.476408847Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

alpine-net의 게이트웨이는 172.18.0.1로 설정되었네요.

 

3. 컨테이너 생성

컨테이너 생성시 --network 옵션으로 특정 네트워크와 연결하도록 할 수 있습니다.

--network의 경우 오직 하나의 네트워크만 연결할 수 있기때문에 두 개 이상의 네트워크와 연결하기 위해서는 docker network connect 명령어로 네트워크 연결을 추가해 주어야 합니다.

 

sudo docker run -dit --name alpine1 --network alpine-net alpine ash
sudo docker run -dit --name alpine2 --network alpine-net alpine ash
sudo docker run -dit --name alpine3 alpine ash
sudo docker run -dit --name alpine4 --network alpine-net alpine ash
sudo docker network connect bridge alpine4

 

컨테이너가 잘 실행되었는지 확인해 주세요.

sudo docker container ls
$ sudo docker container ls
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
9a2c58614afb   alpine    "ash"     45 seconds ago   Up 44 seconds             alpine4
e68539504568   alpine    "ash"     45 seconds ago   Up 45 seconds             alpine3
ee093b4e0486   alpine    "ash"     46 seconds ago   Up 45 seconds             alpine2
a25b486be14b   alpine    "ash"     46 seconds ago   Up 45 seconds             alpine1

 

4. bridge와 alpine-net inspect 확인

bridge와 alpine-net에 컨테이너가 잘 연결되었는지 확인해 보겠습니다.

 

bridge

sudo docker network inspect bridge
$ sudo docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "ba8fb027e7df950bad008b1d3c61ed4a7b202320480c42e580bb73a9cb944ea6",
        "Created": "2023-08-01T06:04:25.041899309Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "9a2c58614afb10273f35c8ff44c5cf7d6ff3fcd6fca6bed0bb43c17e7bd2a015": {
                "Name": "alpine4",
                "EndpointID": "3d89afb9a32b40a0d62e2bb0545467e47b4bfe0d93a664edbb685230b86d0923",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "e6853950456831a0cfce048ea6cac68784d3f2a4db1d297bb1898c2c53ea9983": {
                "Name": "alpine3",
                "EndpointID": "58bde47aa6105bcd7919f54587c5288478f31fe90da75f645fba1d5625df981d",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

alpine3와 alpine4가 잘 연결되었습니다.

 

alpine-net

sudo docker network inspect alpine-net
$ sudo docker network inspect alpine-net
[
    {
        "Name": "alpine-net",
        "Id": "7cd6af8149a45f3c645a6edabb9461cd071a4d73e410182df72a464914bd1f55",
        "Created": "2023-08-01T08:00:40.476408847Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "9a2c58614afb10273f35c8ff44c5cf7d6ff3fcd6fca6bed0bb43c17e7bd2a015": {
                "Name": "alpine4",
                "EndpointID": "9fb20e886bf54b7eedf89e4f31940a2e0f8336f816a5134b647fe2d6634ef7c3",
                "MacAddress": "02:42:ac:12:00:04",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
            },
            "a25b486be14b59b65ac59fbc74e8a7e18d3cf0ed7d471fef9cb7d080c673c607": {
                "Name": "alpine1",
                "EndpointID": "4840785f03e8a1c88c20a7599eb7eb94e42c5276d1e604bd3d1af524fc84fd7e",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "ee093b4e0486bb8a58d0dcf0bfe768affbb44e1e4ddee7f7a229906adb0430c5": {
                "Name": "alpine2",
                "EndpointID": "74acf4fb3684b7d3ad24a915db492ac82a1eb34564b052280ad4284bd778151c",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

alpine1, alpine2, alpine4 모두 잘 연결되었습니다.

 

5. alpine1 -> alpine2 통신 테스트

alpine1에 연결해서 통신 테스트를 진행해 보겠습니다.

 

sudo docker attach alpine1

 

 

앞서 진행한 통신 테스트 중 컨테이너 이름으로 통신을 시도했었습니다.

이번 통신 테스트에서 다시 한 번 시도해 보겠습니다.

ping -c 2 alpine2
# ping -c 2 alpine2
PING alpine2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.131 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.086 ms

--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.086/0.108/0.131 ms

이번 테스트에서는 정상적으로 통신이 완료된 것을 확인할 수 있습니다.

 

alpine-net처럼 직접 생성한 네트워크에 연결된 컨테이너들은 IP 주소와 컨테이너 이름으로도 통신 할 수 있습니다.

이 기능을 automatic service discovery 라고 부른다네요.

 

자기 자신 alpine1과 alpine4도 직접 테스트해 보세요!

 

6. alpine1 -> alpine3 통신

ping -c 2 alpine3
# ping -c 2 alpine3
ping: bad address 'alpine3'

alpine3는 같은 alpine-net에 연결되어있지 않아 컨테이너 명으로는 통신할 수 없습니다.

 

그럼 IP 주소로는 어떨까요?

ping -c 2 172.17.0.2
# ping -c 2 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes

--- 172.17.0.2 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss

역시나 IP 주소로도 통신할 수 없습니다.

 

7. alpine4 -> ? 통신

alpine1 연결을 종료(CTRL + p, q)하고 alpine4에 연결해주세요.

sudo docker attach alpine4

 

alpine4의 경우 bridge와 alpine-net 모두 연결되어 있습니다.

alpine1, alpine2, alpin3 각각 통신 테스트를 진행해 보겠습니다.

 

alpine1

# ping -c 2 alpine1
PING alpine1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.123 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.084 ms

--- alpine1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.084/0.103/0.123 ms

 

alpine2

# ping -c 2 alpine2
PING alpine2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.117 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.083 ms

--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.083/0.100/0.117 ms

 

alpine3

# ping -c 2 alpine3
ping: bad address 'alpine3'
# ping -c 2 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.286 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.168 ms

--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.168/0.227/0.286 ms

 

같은 alpine-net 네트워크에 연결된 컨테이너에는 컨테이너 이름으로 통신할 수 있었지만, bridge 네트워크에 연결된 alpine3는 automatic service discovery 를 지원하지 않아 IP 주소로만 통신 가능한 것을 확인 할 수 있었습니다.

 

8. 외부와의 통신

마지막으로 외부 인터넷과 정상적으로 통신 가능한지 확인해 보도록 하겠습니다.

# ping -c 2 google.com
PING google.com (142.251.42.174): 56 data bytes
64 bytes from 142.251.42.174: seq=0 ttl=104 time=26.146 ms
64 bytes from 142.251.42.174: seq=1 ttl=104 time=26.265 ms

--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 26.146/26.205/26.265 ms

 

외부 인터넷과도 잘 통신하네요 ^^

 

9. 컨테이너 삭제, 정지 및 네트워크 삭제

sudo docker container stop alpine1 alpine2 alpine3 alpine4
sudo docker container rm alpine1 alpine2 alpine3 alpine4
sudo docker network rm alpine-net

 

 

참고

https://docs.docker.com/network/network-tutorial-standalone/

 

Networking with standalone containers

 

docs.docker.com

 

Comments