[docker] docker 네트워크 - 네트워킹 자습서 (4)
카테고리: docker
태그: docker
🎯네트워킹 자습서
- 브리지 네트워크 자습서
- 호스트 네트워킹 자습서
브리지 네트워크 자습서
기본 브리지 네트워크: Docker가 자동으로 설정 하는 기본bridge네트워크를 사용하는 방법을 보여줍니다.사용자 정의 브리지 네트워크: 동일한 Docker 호스트에서 실행되는 컨테이너를 연결하기 위해 고유한 사용자 지정 브리지 네트워크를 만들고 사용하는 방법을 보여줍니다.
기본 브리지 네트워크 사용
- 프로덕션 환경에서
기본 브리지 네트워크를 사용하는 것은 권장되지 않습니다. - 프로덕션 환경에서 사용하려는 경우
사용자 정의 브리지 네트워크사용을 고려하십시오.
# TODO 1. docker network ls
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
b0639baf7651 bridge bridge local
58579e13e100 host host local
64fd52749656 none null local
# TODO 2. alpine 이미지의 기본 쉘인 ash를 실행하는 두 개의 컨테이너를 시작합니다.
$ docker run -dit --name alpine1 alpine ash
3a5c906729cc8f1bfa85ad1cc1cb84ad56188865ec521eb8bf17e7ed7b076c13
$ docker run -dit --name alpine2 alpine ash
d1fe432fb7d15985292d3b5b4ae31dc781ec358e8231e1e9466eeedc9e76f31b
# --network 플래그를 지정하지 않았기 때문에 기본 브리지 네트워크에 연결됩니다.
# TODO 3. docker network inspect bridge
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "b0639baf76517dc10dfcc224aa5653c47c465d394d594d06594edab94e336757",
"Created": "2023-01-25T12:15:14.77016413Z",
"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": {
"3a5c906729cc8f1bfa85ad1cc1cb84ad56188865ec521eb8bf17e7ed7b076c13": {
"Name": "alpine1",
"EndpointID": "eeccb2d8346a7fd1d5e0ff097bcf3071946bb5ac1c6821661cea603f04ff05a4",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"d1fe432fb7d15985292d3b5b4ae31dc781ec358e8231e1e9466eeedc9e76f31b": {
"Name": "alpine2",
"EndpointID": "c5d382fdc5c481b32881d3cdab0ee518a8486edd56655abcd5d71a245f5e6159",
"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": {}
}
]
# 맨 위에는 Docker 호스트와 bridge 네트워크 사이의 게이트웨이 IP 주소를 포함하여 네트워크에 대한 정보가 나열됩니다.
# Containers 키 아래에는 연결된 각 컨테이너가 가진 IP 주소에 대한 정보가 나열됩니다.
# TODO 4. 컨테이너 내부에 attach하여 ip 정보를 확인합니다.
$ docker attach alpine1
/ # 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
458: eth0@if459: <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
# 컨테이너에 접속했을 때 출력되는 '/ #' 문자는 컨테이너내에서 root 유저 프롬프트를 획득하였음을 알 수 있습니다.
# 첫 번째 인터페이스는 루프백이고 etho0@if459 인터페이스는 이전 단계에서 inspect 명령으로 확인한 IP 주소와 같음을 확인할 수 있습니다.
# TODO 5. alpine1 컨테이너에서 핑을 통해 인터넷에 연결할 수 있는지 확인합니다.
/ # ping -c 2 google.com
PING google.com (142.250.206.206): 56 data bytes
64 bytes from 142.250.206.206: seq=0 ttl=54 time=36.682 ms
64 bytes from 142.250.206.206: seq=1 ttl=54 time=35.721 ms
--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 35.721/36.201/36.682 ms
# TODO 6. alpine1 컨테이너에서 alpine2 컨테이너의 IP 주소로 ping 합니다.
/ # 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.086 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.088 ms
--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.086/0.087/0.088 ms
# TODO 7. alpine1 컨테이너에서 alpine2 컨테이너의 이름으로 ping 합니다.
/ # ping -c 2 alpine2
ping: bad address 'alpine2'
# 기본적으로 컨테이너간에는 IP 주소를 이용한 통신이 가능하지만 컨테이너 이름으로는 통신이 불가능함을 알 수 있다.
사용자 정의 브리지 네트워크 사용
# TODO 1. alpine-net 사용자 정의 브리지 네트워크를 만듭니다.
$ docker network create --driver bridge alpine-net
46be04a90dc73334f3a803f02f4c9d2e071f6fde48baf5cca7056c5bc479b430
# --driver bridge 플래그는 기본값이므로 생략할 수 있습니다.
# TODO 2. docker network ls
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
46be04a90dc7 alpine-net bridge local
b0639baf7651 bridge bridge local
58579e13e100 host host local
64fd52749656 none null local
# TODO 3. docker network inspect alpine-net
$ docker network inspect alpine-net
[
{
"Name": "alpine-net",
"Id": "46be04a90dc73334f3a803f02f4c9d2e071f6fde48baf5cca7056c5bc479b430",
"Created": "2023-01-31T10:10:03.563456932Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.112.0/20",
"Gateway": "192.168.112.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
# inspect 명령의 결과로 현재 alpine-net 네트워크에 연결된 컨테이너가 없음을 확인할 수 있습니다.
# 게이트웨이 주소가 172.17.0.1인 기본 브리지 네트워크와 달리 이 네트워크의 게이트웨이 주소는 192.168.112.1 입니다.
# TODO 4. 4개의 컨테이너를 만듭니다.
$ docker run -dit --name alpine1 --network alpine-net alpine ash
4c31b32f68960d229e18af07d3628ff6bb49cd58923439f35a488f0e7ee12095
$ docker run -dit --name alpine2 --network alpine-net alpine ash
dda353744a09c9b776535d7ddfbd2873549dd61bfcaef4e7b67235241f457615
$ docker run -dit --name alpine3 alpine ash
503fc14e7529b2ad4193afe5b355aa4ca5447504ce7bfbd0667633c0b5a15ce6
$ docker run -dit --name alpine4 --network alpine-net alpine ash
b432f1efe117503393747bb157c006f71003ae24eacae05fd64cb82f1dc876a5
$ docker network connect bridge alpine4
# alpine3 컨테이너는 --network 플래그를 사용하지 않았습니다.
# alpine4 컨테이너는 'docker network connect' 명령을 이용해 기본 브리지 네트워크를 추가 연결하였습니다.
# TODO 5.1 bridge 네트워크를 검사합니다.
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "b0639baf76517dc10dfcc224aa5653c47c465d394d594d06594edab94e336757",
"Created": "2023-01-25T12:15:14.77016413Z",
"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": {
"503fc14e7529b2ad4193afe5b355aa4ca5447504ce7bfbd0667633c0b5a15ce6": {
"Name": "alpine3",
"EndpointID": "244f187fa6be85b1d2814ce81ab9fd6f16be84ad1f46c51324ad27abe70ca8b0",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"b432f1efe117503393747bb157c006f71003ae24eacae05fd64cb82f1dc876a5": {
"Name": "alpine4",
"EndpointID": "c29061a43f4ab5d69e9a1fc34cbc8e4851df5179e9a70f0afbdfa272464e89ca",
"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": {}
}
]
# TODO 5.2 alpine-net 네트워크를 검사합니다.
$ docker network inspect alpine-net
[
{
"Name": "alpine-net",
"Id": "46be04a90dc73334f3a803f02f4c9d2e071f6fde48baf5cca7056c5bc479b430",
"Created": "2023-01-31T10:10:03.563456932Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.112.0/20",
"Gateway": "192.168.112.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"4c31b32f68960d229e18af07d3628ff6bb49cd58923439f35a488f0e7ee12095": {
"Name": "alpine1",
"EndpointID": "229a0ae43e90fbf25c3988af4f40f51f07fd76f74ccb4fa1e42650f2174189f1",
"MacAddress": "02:42:c0:a8:70:02",
"IPv4Address": "192.168.112.2/20",
"IPv6Address": ""
},
"b432f1efe117503393747bb157c006f71003ae24eacae05fd64cb82f1dc876a5": {
"Name": "alpine4",
"EndpointID": "bb16c131a432a9f47426a6233021a6b1b61ed50040b7897204b9b4967b6de03a",
"MacAddress": "02:42:c0:a8:70:04",
"IPv4Address": "192.168.112.4/20",
"IPv6Address": ""
},
"dda353744a09c9b776535d7ddfbd2873549dd61bfcaef4e7b67235241f457615": {
"Name": "alpine2",
"EndpointID": "5982f51cd390e9abed2deb4bf15dfeec090ea67e05cc33f619389ae1d458fe19",
"MacAddress": "02:42:c0:a8:70:03",
"IPv4Address": "192.168.112.3/20",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# alpine3, alpine4 컨테이너는 기본 브리지에 연결되었습니다.
# alpine1, alpine2, alpine4 컨테이너는 alpine-net 네트워크에 연결되었습니다.
# TODO 6. alpine1 컨테이너에 attach 하여 alpine2, alpine4 컨테이너 이름으로 ping 합니다.
$ docker attach alpine1
/ # ping -c 2 alpine2
PING alpine2 (192.168.112.3): 56 data bytes
64 bytes from 192.168.112.3: seq=0 ttl=64 time=1.503 ms
64 bytes from 192.168.112.3: seq=1 ttl=64 time=0.076 ms
--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.076/0.789/1.503 ms
/ # ping -c 2 alpine4
PING alpine4 (192.168.112.4): 56 data bytes
64 bytes from 192.168.112.4: seq=0 ttl=64 time=2.980 ms
64 bytes from 192.168.112.4: seq=1 ttl=64 time=0.088 ms
--- alpine4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.088/1.534/2.980 ms
# 사용자 정의 네트워크에서는 컨테이너 IP 주소로 통신할 수 있을 뿐만 아니라 컨테이너 이름을 IP 주소로 확인할 수도 있습니다. 이 기능을 자동 서비스 검색이라고 합니다.
# TODO 7. alpine3 컨테이너에 ping 합니다.
/ # 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
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
# alpine-net 네트워크에만 연결된 컨테이너에서 alpine3 컨테이너로 통신할 수 있는 방법은 없습니다.
# TODO 8. apine4 컨테이너에 attach 하여 다른 컨테이너에 ping 합니다.
/ # ping -c 2 alpine1
PING alpine1 (192.168.112.2): 56 data bytes
64 bytes from 192.168.112.2: seq=0 ttl=64 time=0.065 ms
64 bytes from 192.168.112.2: seq=1 ttl=64 time=0.097 ms
--- alpine1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.065/0.081/0.097 ms
/ # ping -c 2 alpine2
PING alpine2 (192.168.112.3): 56 data bytes
64 bytes from 192.168.112.3: seq=0 ttl=64 time=0.299 ms
64 bytes from 192.168.112.3: seq=1 ttl=64 time=0.104 ms
--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.104/0.201/0.299 ms
/ # 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.229 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.115 ms
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.115/0.172/0.229 ms
# alpine4 컨테이너는 기본 브리지 네트워크와 사용자 정의 브리지 네트워크에 모두 연결되어 있습니다.
# 따라서 alpine1, alpine2, alpine3 컨테이너 모두와 통신할 수 있습니다.
# 다만, alpine3 컨테이너는 기본 브리지 네트워크로 연결되어 있기 때문에 컨테이너 이름이 아닌 IP 주소로만 통신할 수 있습니다.
호스트 네트워킹 자습서
- 이 자습서의 목표는 Docker 호스트의 80 포트에 직접 바인딩 되는
nginx컨테이너를 시작하는 것입니다. - 네트워킹 관점에서
nginx프로세스가 컨테이너가 아닌 Docker 호스트에서 직접 실행되는 것과 동일한 수준의 격리입니다. - 그러나 저장소, 프로세스, 네임스페이스와 같은 다른 모든 리소스에서는
nginx프로세스가 호스트에서 격리됩니다.
# TODO 1. nginx 컨테이너를 시작합니다.
$ docker run --rm -d --network host --name my_nginx nginx
da59ee895a0a52edb5f99bedab52e4f9ac64727b4520fac4d10f7b36334e6118
# TODO 2. curl http://localhost:80 으로 이동하여 Nginx에 엑세스 합니다.
$ curl http://localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# TODO 3. Docker 호스트에서 ifconfig 명령을 사용하여 새 인터페이스가 생성되지 않았는지 검사합니다.
$ ifconfig
# host 네트워크를 통해 생성된 컨테이너는 Docker 호스트에 새로운 인터페이스를 생성하지 않습니다.
# TODO 4. Docker 호스트에서 netstat 명령을 사용하여 80 포트에 바인딩된 프로세스를 확인합니다.
$ docker container inspect my_nginx | grep -w Pid
"Pid": 7092,
$ netstat -tnlp | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 7092/nginx: master
tcp6 0 0 :::80 :::* LISTEN 7092/nginx: master
📌출처
👍 개인 공부 기록용 블로그입니다. 오류나 조언이 있으시면 언제든지 댓글 혹은 메일로 남겨주시면 감사하겠습니다! 😄
댓글남기기