docker基础之六network-1-singlehost
问:
docker提供的几种原生网络,及如何创建自定义网络。
容器之间如何通信,及容器与外界如何交互
docker网络从覆盖范围可分为单host上的容器网络和跨多个host的网络
docker安装时会自动在host上创建三个网络:
docker -H master network ls NETWORK ID NAME DRIVER SCOPE ceadc77129ea bridge bridge local 48990edc38c7 host host local 50fe527f5883 none null local
1) none 只有lo create一个容器可以指定--network=none
2) host 在容器中能看到host的网络,并且hostname都是host的,--network=host
3) bridge --network=bridge
[root@master ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.02421dc4d59d no [root@master ~]# docker -H master run -d httpd 027256d40752467ba4d35186c15302029b40ebe8598a666bab47875042d28338 [root@master ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.02421dc4d59d no vethd507466
[root@master ~]# docker -H master exec -it 027 bash
root@027256d40752:/usr/local/apache2# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
[root@master ~]# docker -H master network inspect bridge
[
{
"Name": "bridge",
"Id": "ceadc77129ea6f87720e8f8722cf89f1f508b38b317837f039f342e4f11b43cd",
"Created": "2018-07-25T13:44:05.507043765+08:00",
"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,
"Containers": {
"027256d40752467ba4d35186c15302029b40ebe8598a666bab47875042d28338": {
"Name": "stoic_agnesi",
"EndpointID": "305df56da0a7d0d3f4ff3e26298dd9d3210e353b1d73ec26ad109d322cb9c7ab",
"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": {}
}
]
注意:
默认bridge分配的网络为172.17.0.0/16网段
想要修改该网段,指定bridge docker0的地址:
[root@nas4 docker]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://i5vp5biq.mirror.aliyuncs.com"],
"bip": "10.5.14.1/24"
}
创建bridge的driver
1)
[root@master ~]# docker -H master network create --driver bridge my_net
763737ede0c100f89bd0bcc4082b675c15fdd996b566e85596693450c4cda753
[root@master ~]# brctl show
bridge name bridge id STP enabled interfaces
br-763737ede0c1 8000.02420a7b15f6 no
docker0 8000.02421dc4d59d no vethd507466
[root@master ~]# docker -H master network inspect my_net
[
{
"Name": "my_net",
"Id": "763737ede0c100f89bd0bcc4082b675c15fdd996b566e85596693450c4cda753",
"Created": "2018-07-25T16:36:25.559888841+08:00",
"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,
"Containers": {},
"Options": {},
"Labels": {}
}
]
2)指定 --subnet和--gateway
[root@master ~]# docker -H master network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net2
fcfcdf9dfadf1578cda64066817d702d6003c39f98555519cc47c57596e231f1
[root@master ~]# brctl show
bridge name bridge id STP enabled interfaces
br-763737ede0c1 8000.02420a7b15f6 no
br-fcfcdf9dfadf 8000.024265dfe391 no
docker0 8000.02421dc4d59d no vethd507466
[root@master ~]# docker -H master network inspect my_net2
[
{
"Name": "my_net2",
"Id": "fcfcdf9dfadf1578cda64066817d702d6003c39f98555519cc47c57596e231f1",
"Created": "2018-07-25T16:40:06.272346007+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.22.16.0/24",
"Gateway": "172.22.16.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
3)启动容器指定新网络,由docker自动从subnet分配ip
[root@master ~]# docker -H master run -it --network=my_net2 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:16:10:02 brd ff:ff:ff:ff:ff:ff
inet 172.22.16.2/24 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe16:1002/64 scope link
valid_lft forever preferred_lft forever
4)启动容器指定新网络并--ip指定静态ip,条件就是创建网络时指定--subnet的网络才可以指定静态ip
[root@master ~]# docker -H master run -it --network=my_net2 --ip 172.22.16.200 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
22: eth0@if23: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:16:10:c8 brd ff:ff:ff:ff:ff:ff
inet 172.22.16.200/24 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe16:10c8/64 scope link
valid_lft forever preferred_lft forever
[root@master ~]# docker -H master run -it --network=my_net --ip 172.18.0.200 busybox /usr/bin/docker-current: Error response from daemon: User specified IP address is supported only when connecting to networks with user configured subnets.
5)容器不同网络间通讯
A、通过额外添加同网络的网卡
docker -H master network connect my_net2 027256d40752
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
28: eth1@if29: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:16:10:03 brd ff:ff:ff:ff:ff:ff
inet 172.22.16.3/24 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe16:1003/64 scope link
valid_lft forever preferred_lft forever
# ping 172.22.16.200
PING 172.22.16.200 (172.22.16.200) 56(84) bytes of data.
64 bytes from 172.22.16.200: icmp_seq=1 ttl=64 time=0.108 ms
64 bytes from 172.22.16.200: icmp_seq=2 ttl=64 time=0.107 ms
^C
--- 172.22.16.200 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.107/0.107/0.108/0.010 ms
B、 joined,多个容器共享一个网络栈,即共享配置信息,127.0.0.1也可通信,因为ip与mac共用
[root@master ~]# docker run -d -it --name=web1 docker.io/httpd
fc4c370344afb10738319fd9904fe22bc06ab92948fb37135d880de7d9bf336d
[root@master ~]# docker run -it --network=container:web1 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
/ #
[root@master ~]# docker exec -it web1 bash
root@fc4c370344af:/usr/local/apache2# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
root@fc4c370344af:/usr/local/apache2#
小结:
容器间通信的三种方式:ip,docker dns server或joined容器
1.ip通信:两容器必须有属于同一个网络的网卡
如:容器创建时通过--network指定相应的网络,或者docker network connect
2.docker dns server
docker1.10版本开始,docker daemon开始内嵌dns server ,使容器直接通过“容器”名通信,只要在启动时用--name为容器命名即可
docker dns有个限制:只能在user-defined网络中使用,默认bridge网络无使用dns
3.joined容器
joined容器可以使两个容器共享一个网络栈,共享网卡和配置信息,joined容器之间可以通过127.0.0.1直接通信
先创建一个httpd容器,名字为web1
docker run -d -it --name=web1 httpd
再创建busybox容器并通过--network=container:web1指定joined容器为web1
docker run -it --network=container:web1 busybox
ip a
确认下共享了网络栈,ip与mac完全一样,
docker network inspect bridge
且busybox可以直接用127.0.0.1访问web1的http服务
joined容器非常适合的场景:
1.不同容器中程序希望通过loopback高效快速地通信
2.监控
容器与外部通信
1.容器访问外界
当前实验环境,docker host可以访问外网,容器也可以
[root@master ~]# docker run -it busybox
/ # ping -c 3 www.baidu.com
PING www.baidu.com (61.135.169.121): 56 data bytes
64 bytes from 61.135.169.121: seq=0 ttl=56 time=3.199 ms
64 bytes from 61.135.169.121: seq=1 ttl=56 time=4.292 ms
64 bytes from 61.135.169.121: seq=2 ttl=56 time=7.405 ms
--- www.baidu.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 3.199/4.965/7.405 ms
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:3/64 scope link
valid_lft forever preferred_lft forever
/ #
[root@master ~]# iptables -t nat -S -P PREROUTING ACCEPT -P INPUT ACCEPT -P OUTPUT ACCEPT -P POSTROUTING ACCEPT -N DOCKER -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE -A POSTROUTING -s 172.18.0.0/16 ! -o br-763737ede0c1 -j MASQUERADE -A POSTROUTING -s 172.22.16.0/24 ! -o br-fcfcdf9dfadf -j MASQUERADE -A DOCKER -i docker0 -j RETURN -A DOCKER -i br-fcfcdf9dfadf -j RETURN -A DOCKER -i br-763737ede0c1 -j RETURN
####nat表中规则-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
其含义是:来自 172.17.0.0/16 网段的包,目标地址是外网(! -o docker0),就把它交给 MASQUERADE 处理。而 MASQUERADE 的处理方式是将包的源地址替换成host的地址发送出去,即做了一次网络地址转换(NAT)
[root@master ~]# ip r
default via 192.168.1.1 dev ens33 proto dhcp metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
172.18.0.0/16 dev br-763737ede0c1 proto kernel scope link src 172.18.0.1
172.22.16.0/24 dev br-fcfcdf9dfadf proto kernel scope link src 172.22.16.1
192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.218 metric 100
[root@master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:3b:ca:d2 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.218/24 brd 192.168.1.255 scope global noprefixroute dynamic ens33
valid_lft 82084sec preferred_lft 82084sec
inet6 fe80::4fcb:8d36:f2f0:3f5f/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:0f:2b:9e:0a brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:fff:fe2b:9e0a/64 scope link
valid_lft forever preferred_lft forever
4: br-fcfcdf9dfadf: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:81:ae:d2:b8 brd ff:ff:ff:ff:ff:ff
inet 172.22.16.1/24 scope global br-fcfcdf9dfadf
valid_lft forever preferred_lft forever
5: br-763737ede0c1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:1c:48:89:68 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 scope global br-763737ede0c1
valid_lft forever preferred_lft forever
7: vethc393948@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 02:e9:3e:7e:21:d1 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::e9:3eff:fe7e:21d1/64 scope link
valid_lft forever preferred_lft forever
9: veth96720b7@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether c6:72:9b:9b:1a:40 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::c472:9bff:fe9b:1a40/64 scope link
valid_lft forever preferred_lft forever
[root@master ~]# tcpdump -i docker0 -n icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:29:43.930573 IP 172.17.0.3 > 61.135.169.121: ICMP echo request, id 4096, seq 131, length 64
10:29:43.934103 IP 61.135.169.121 > 172.17.0.3: ICMP echo reply, id 4096, seq 131, length 64
[root@master ~]# tcpdump -i ens33 -n icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
10:30:10.956862 IP 192.168.1.218 > 61.135.169.121: ICMP echo request, id 4096, seq 158, length 64
10:30:10.959752 IP 61.135.169.121 > 192.168.1.218: ICMP echo reply, id 4096, seq 158, length 64
[root@master ~]#
数据处理过程:
1)busybox 发送 ping 包:172.17.0.3 > www.bing.com。
2)docker0 收到包,发现是发送到外网的,交给 NAT 处理。
3)NAT 将源地址换成 ens33 的 IP:192.168.1.218 > www.bing.com。
4)ping 包从 ens33 发送出去,到达 www.bing.com。
2.外界访问容器
端口映射:
docker可将容器对外提供服务的端口映射到host的某个端口,外网通过该端口访问容器
例:
docker run -d -p 80 httpd 或 docker run -d -p 8080:80 httpd
httpd容器的80被映射到host的随机端口或指定端口8080
查看
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 59cfb2a67ffd httpd "httpd-foreground" 5 seconds ago Up 3 seconds 0.0.0.0:32768->80/tcp jovial_mccarthy 551ffae44ee3 httpd "httpd-foreground" 13 seconds ago Up 12 seconds 0.0.0.0:8080->80/tcp stupefied_mestorf docker port 59cfb2a67ffd 551ffae44ee3 80/tcp -> 0.0.0.0:32768 80/tcp -> 0.0.0.0:8080 ps -ef |grep docker-proxy root 8181 7304 0 10:16 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 32768 -container-ip 172.17.0.2 -container-port 80 root 8370 7304 0 10:17 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080 -container-ip 172.17.0.3 -container-port 80
每一个映射的端口,host都会启动一个docker-proxy进程来处理访问容器的流量
curl 10.1.1.15:32768 <html><body><h1>It works!</h1></body></html> curl 10.1.1.15:8080 <html><body><h1>It works!</h1></body></html>
跨主机网络通信,待续docker基础之六network-2~...

浙公网安备 33010602011771号