前言
Docker 目前提供以下網路模式, None, Bridge, Host
None
除了 loopback interface (127.0.0.1) 之外無其他網路介面,
所以無法存取外部網路
andy_lai@cloudshell:~$ docker run -it --network=none ubuntu:14.04 /bin/bash
Digest: sha256:ffc76f71dd8be8c9e222d420dc96901a07b61616689a44c7b3ef6a10b7213de4
root@71aa5f112c7e:/# ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Host
使用和宿主機 (Host) 一樣的網路設定, 效能會比較好, 但仍不建議使用, 需要考慮網路安全性的問題, 除此之外也會使失去容器隔離的好處
Bridge
Docker 預設會在宿主機 (Host) 上建立一個 docker0 的網路介面,
容器可以透過這網路介面跟外界溝通, 也可以透過這介面作容器間的溝通, 事實上
docker0 扮演著一個虛擬的網路橋接器, 當以 Bridge
的網路模式建立新的容器的時候
andy_lai@cloudshell:~$ docker run -it -p 8080:8080 my-docker
docker0 會被接上虛擬網卡 veth3cc413e
andy_lai@cloudshell:~$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242c76b7a80 no veth3cc413e
veth3cc413e 是執行完 docker run -it -p 8080:8080 my-docker 之後 docker 自動幫我們產生的, 在宿主機 (Host) 上使用 ifconfig 指令就可以看到這張虛擬網卡的資訊
andy_lai@cloudshell:~$ ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1460
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:c7:6b:7a:80 txqueuelen 0 (Ethernet)
RX packets 2552 bytes 171821 (167.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2472 bytes 434020 (423.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 38407 bytes 92400734 (88.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 33461 bytes 12551745 (11.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 18447 bytes 8319183 (7.9 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 18447 bytes 8319183 (7.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth3cc413e: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1460
ether 2e:68:27:46:6a:8d txqueuelen 0 (Ethernet)
RX packets 2552 bytes 207549 (202.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2472 bytes 434020 (423.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth3cc413e 與容器內的 eth0 構成一個 veth pair, 網路橋接器可以根據它的內容將封包轉送到對應的網路介面
如果想要知道到 Bridge 網路更詳細的資訊, 可以使用以下指令來顯示
andy_lai@cloudshell:~$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "d7d9e226496db23fc37457cee54f768496855b89299fd5ac37ca2b4ac4225d9b",
"Created": "2020-05-17T07:03:40.711615067Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.18.0.0/16"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"7c2276df1d04f60e3b604f9fb01d81f7279815e148a1f34bb04dc40de6c9e701": {
"Name": "jolly_kapitsa",
"EndpointID": "5b4f48db790c05a73a0764cf30f6b0a5a0b5de87ca439d9daec8576aa59cfb47",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.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": "1460"
},
"Labels": {}
}
]
以上的資訊可以看到 docker0 的網路資訊裡有容器 jolly_kapitsa 的 IP 位址 172.18.0.2
而當容器對外發出請求的時候, docker0 會把收到的封包交給 MASQUERADE 處理,
將來源地址轉換成宿主機 (Host) 的地址之後才會送出 (即NAT)
從宿主機 (Host) 上的 iptables 就可以看出這個規則
andy_lai@cloudshell:~$ sudo iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:80
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:80
-A OUTPUT -d 169.254.169.254/32 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 169.254.169.254:80
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.18.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.18.0.2/32 -d 172.18.0.2/32 -p tcp -m tcp --dport 8080 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.18.0.2:8080
留言
張貼留言