docker 5种网络管理
一、有哪五种模式网络:
docker的网络模式大致可以分成五种类型:
-
默认是bridge模式网络 使用–net =bridge指定,默认网络驱动程序。当你的应用程序在需要通信的独立容器中运行时,通常会使用桥接网络。
-
host模式网络 使用–net =host指定,对于独立容器,删除容器和Docker主机之间的网络隔离,并直接使用主机的网络
-
none模式网络 使用–net =none指定,对于此容器,禁用所有网络
另外两种: -
container模式网络 使用–net =container:指定容器名,可以多个容器共用一个网络
-
user-defined模式网络:
- overlay模式网络 使用--net=overlay,覆盖网络将多个Docker守护程序连接在一起,并使群集服务能够相互通信。还可以使用覆盖网络来促进群集服务和独立容器之间的通信,或者在不同Docker守护程序上的两个独立容器之间进行通信
- macvlan:Macvlan网络允许您为容器分配MAC地址,使其显示为网络上的物理设备。Docker守护程序通过其MAC地址将流量路由到容器。macvlan 在处理期望直接连接到物理网络的传统应用程序时,使用驱动程序有时是最佳选择,而不是通过Docker主机的网络堆叠进行路由
在安装完docker之后,宿主机上会创建三个网络:
默认docker主机会存在三种类型的网络,可以使用docker network ls命令查看
[root@VM_0_6_centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f88b1c490d20 bridge bridge local
0954ad9627bc host host local
7dbe186a84e8 none null local
1.bridge模式网络
容器的默认网络模式,docker在安装时会创建一个名为docker0的Linux bridge,在不指定--network的情况下,创建的容器都会默认挂到docker0上面
在该模式(见下图)中,Docker守护进程创建了一个虚拟以太网桥`docker0`,附加在其上的任何网卡之间都能自动转发数据包。默认情况下,守护进程会创建一对对等接口,将其中一个接口设置为容器的eth0接口,另一个接口放置在宿主机的命名空间中,从而将宿主机上的所有容器都连接到这个内部网络上。同时,守护进程还会从网桥的私有地址空间中分配一个IP地址和子网给该容器
1.1 如,docker主机会有一个默认使用的桥接网卡bridge0,它是在运行docker容器时,如果不指定网络,默认使用的网络:docker0
[root@VM_0_6_centos ~]# 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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:69:06:60 brd ff:ff:ff:ff:ff:ff
inet 172.16.0.6/20 brd 172.16.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe69:660/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:74:13:f5:ff brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:74ff:fe13:f5ff/64 scope link
valid_lft forever preferred_lft forever
1.2 当运行一个容器时,我们可以看到在docker主机上多了一个网卡(vethd579570@if38),而且master指向docker0
[root@VM_0_6_centos ~]# docker run -d -P --net=bridge nginx:1.9.1
59abbf7dbeedf974349fd971970300e311d4ff56aef7e17f8071ec84e8b8e795
[root@VM_0_6_centos ~]# 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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:69:06:60 brd ff:ff:ff:ff:ff:ff
inet 172.16.0.6/20 brd 172.16.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe69:660/64 scope link
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:74:13:f5:ff brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:74ff:fe13:f5ff/64 scope link
valid_lft forever preferred_lft forever
39: vethd579570@if38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 7e:79:90:55:97:1d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::7c79:90ff:fe55:971d/64 scope link
valid_lft forever preferred_lft forever
因为bridge模式是Docker的默认设置,所以你也可以使用`docker run -d -P nginx:1.9.1`。如果你没有使用-P(发布该容器暴露的所有端口)或者-p
host_port:container_port(发布某个特定端口),IP数据包就不能从宿主机之外路由到容器中。
1.3 这时候我们在查看该容器的网络信息(ip地址和网关)。发现它的ip地址和docker0一个网段,网关则是docker0的地址
[root@VM_0_6_centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
59abbf7dbeed nginx:1.9.1 "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:32771->80/tcp, 0.0.0.0:32770->443/tcp competent_cori
[root@VM_0_6_centos ~]# docker inspect -f {{".NetworkSettings.Networks.bridge.IPAddress"}} 59abbf7dbeed
172.17.0.2
[root@VM_0_6_centos ~]# docker inspect -f {{".NetworkSettings.Networks.bridge.Gateway"}} 59abbf7dbeed
172.17.0.1
1.4 bridge网络的特点
使用一个 linux bridge,默认为 docker0
使用veth 对,一头在容器的网络 namespace中,一头在docker0上
该模式下Docker Container不具有一个公有IP,因为宿主机的IP地址与veth pair的IP地址不在同一个网段内
Docker采用NAT方式,将容器内部的服务监听的端口与宿主机的某一个端口进行“绑定”,使得宿主机以外的世界可以主动将网络报文发送至容器内部
外界访问容器内的服务时,需要访问宿主机的 IP 以及宿主机的端口 port
NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。
容器拥有独立、隔离的网络栈;让容器和宿主机以外的世界通过NAT建立通信
我们查看iptables的nat表,可以看到,在POSTROUTING链上做了一个MASQUERADE,源是172.17.0.0/1
2.host模式网络
该模式将禁用Docker容器的网络隔离。因为容器共享了宿主机的网络命名空间,直接暴露在公共网络中。因此,你需要通过端口映射(port mapping)来进行协调。
通过命令--network=host指定,使用host模式的容器可以直接使用docker host的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好
2.1 Host模式并没有为容器创建一个隔离的网络环境。该模式下的Docker容器会和host宿主机共享同一个网络namespace,所以容器可以和宿 主机一样,使用宿主机的eth0,实现和外界的通信。
特点:
这种模式下的容器没有隔离的network namespace
容器的IP地址同 Docker主机的IP地址
需要注意容器中服务的端口号不能与Docker主机上已经使用的端口号相冲突
host模式能够和其它模式共存
2.2 首先我通过ss查看一下,我的docker主机80端口并没有使用。当我启动一个提供nginx应用的容器时,在查看发现我的主机使用了80端口
[root@VM_0_6_centos ~]# ss -lnt |grep 80
[root@VM_0_6_centos ~]# docker run -itd --privileged --name nginx001 --network host nginx:latest
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
f5d23c7fed46: Already exists
918b255d86e5: Pull complete
8c0120a6f561: Pull complete
Digest: sha256:eb3320e2f9ca409b7c0aa71aea3cf7ce7d018f03a372564dbdb023646958770b
Status: Downloaded newer image for nginx:latest
c7ea10aa92dd09b312f844aa70a359861c8da8d4eea2bbae2353505008beea27
[root@VM_0_6_centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c7ea10aa92dd nginx:latest "nginx -g 'daemon of…" About a minute ago Up About a minute nginx001
[root@VM_0_6_centos ~]# ss -lnt |grep 80
LISTEN 0 128 *:80 *:*
2.3 我们还可以通过docker inspect nginx001查看它的网络信息。发现IP地址和网关处根本没有值。因为使用了host网络,它是共用了docker主机的网络
[rootVM_0_6_centos ~]# docker inspect -f {{".NetworkSettings.Networks.bridge.IPAddress"}} nginx001
<no value>
[root@VM_0_6_centos ~]# docker inspect -f {{".NetworkSettings.Networks.bridge.Gateway"}} nginx001
<no value>
2.4 再例如:
[root@VM_0_6_centos ~]# docker run -d --net=host ubuntu:14.04 tail -f /dev/null
Unable to find image 'ubuntu:14.04' locally
14.04: Pulling from library/ubuntu
a7344f52cb74: Pull complete
515c9bb51536: Pull complete
e1eabe0537eb: Pull complete
4701f1215c13: Pull complete
Digest: sha256:2f7c79927b346e436cc14c92bd4e5bd778c3bd7037f35bc639ac1589a7acfa90
Status: Downloaded newer image for ubuntu:14.04
cb5860bbcf61d006c9654cb4678fe3a2b9cb93c2f09cc84da142113d245b6e83
[root@VM_0_6_centos ~]# ip addr | grep -A 2 eth0:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:69:06:60 brd ff:ff:ff:ff:ff:ff
inet 172.16.0.6/20 brd 172.16.15.255 scope global eth0
[root@VM_0_6_centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb5860bbcf61 ubuntu:14.04 "tail -f /dev/null" About a minute ago Up 59 seconds hungry_payne
[root@VM_0_6_centos ~]# docker exec -it cb5860bbcf61 ip addr
inet 172.16.0.6/20 brd 172.16.15.255 scope global eth0
我们可以从上例中看到:容器和宿主机具有相同的IP地址172.16.0.6
。
在下图中,我们可以看到:当使用host模式网络时,容器实际上继承了宿主机的IP地址。该模式比bridge模式更快(因为没有路由开销),但是它将容器直接暴露在公共网络中,是有安全隐患的
3.none模式网络
这种网络模式下容器只有lo回环网络,没有其他网卡。none网络可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。一旦 Docker Container 采用了none网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。在没有网络配置的情况下,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制开发。
3.1 在 none 网络模式下分配固定 ip:
netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境,目前 netns 在 lxc 容器中被用来为容器提供网络。使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样
[root@VM_0_6_centos ~]# docker run -it --name vm5 --net none ubuntu
3.2 这种方式创建没有网络,可以自己指定设置网络
[root@VM_0_6_centos ~]# ip addr
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
4.container模式网络 共享模式
用于容器和容器直接频繁交流的情况。
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
创建容器时使用--network=container:NAME_or_ID这个模式在创建新的容器的时候指定容器的网络和一个已经存在的容器共享一个Network Namespace,但是并不为docker容器进行任何网络配置,这个docker容器没有网卡、IP、路由等信息,需要手动的去为docker容器添加网卡、配置IP等
(1) 查找 other container(即需要被共享网络环境的容器)的网络 namespace;
(2) 将新创建的 Docker Container(也是需要共享其他网络的容器)的 namespace,使用
other container 的 namespace。
Docker Container 的 other container 网络模式,可以用来更好的服务于容器间的通信。
在这种模式下的 Docker Container 可以通过 localhost 来访问 namespace 下的其他容器,传输
效率较高。虽然多个容器共享网络环境,但是多个容器形成的整体依然与宿主机以及其他
容器形成网络隔离。另外,这种模式还节约了一定数量的网络资源。但是需要注意的是,
它并没有改善容器与宿主机以外世界通信的情况
4.1 创建一个nat模式,看一下这个容器ip:
[root@VM_0_6_centos ~]# docker run -it --name busyboxl busybox sh
/ # ip addr
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
34: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # hostname
d9e5c9ad1193
/ #
4.2 创建一个container网络模式的ip,创建完成后,可以看到这两个ip地址是一模一样的,并且是可以直接通信的
[root@VM_0_6_centos ~]# docker run -it --name busybox2 --net=container:busybox1 busybox sh
docker: Error response from daemon: cannot join network of a non running container: 4d33b98101f85aa77e576967c64d8b83b535f99d22d82a89bdd62b15f3f96070.
[root@VM_0_6_centos ~]# ip addr
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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:69:06:60 brd ff:ff:ff:ff:ff:ff
inet 172.16.0.6/20 brd 172.16.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe69:660/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:74:13:f5:ff brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:74ff:fe13:f5ff/64 scope link
valid_lft forever preferred_lft forever
4.3 确认是两个容器:
[root@VM_0_6_centos ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1af412b5e1d7 busybox "sh" 58 seconds ago Created busybox2
4d33b98101f8 busybox "sh" 2 minutes ago Exited (0) About a minute ago busybox1
4.4 None,不会创建网络,里面就不会有ip,最常用的是nat模式和container网络模式,container网络模式用于容器和容器直接频繁交流的情况。
[root@VM_0_6_centos ~]# docker run -it --name none --net=none busybox sh
/ # ip addr
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
/ #
5.user-defined模式
用户自定义模式主要可选的有三种网络驱动:bridge、overlay、macvlan。bridge驱动用于创建类似于前面提到的bridge网络;overlay和macvlan驱动用于创建跨主机的网络。
二、外部网络访问容器内应用
1.-P随机指定一个docker主机端口给容器中的端口做映射
[root@VM_0_6_centos ~]# docker run -itd -P --name nginx001 nginx:latest
b718bc214f766d154b0608819edac97da066e1edbf1617125d4b707ac4b5c6e4
[root@VM_0_6_centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b718bc214f76 nginx:latest "nginx -g 'daemon of…" 8 seconds ago Up 7 seconds 0.0.0.0:32772->80/tcp nginx001
[root@VM_0_6_centos ~]#
2.-p将docker主机的一个端口映射容器的一个端口
[root@VM_0_6_centos ~]# docker run -itd -p 8000:80 --name nginx002 nginx:latest
bb4cce60ff9da6c7e57d24f0a4d63921925e8990a3172c613d25865eb8b8ab50
[root@VM_0_6_centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bb4cce60ff9d nginx:latest "nginx -g 'daemon of…" 13 seconds ago Up 13 seconds 0.0.0.0:8000->80/tcp nginx002
b718bc214f76 nginx:latest "nginx -g 'daemon of…" 2 minutes ago Up 2 minutes 0.0.0.0:32772->80/tcp nginx001
[root@VM_0_6_centos ~]#
访问网站测试(我的docker主机的地址为129.204.207.***,记住要在docker主机上放行32772和8000端口)
首先访问32768端口:129.204.207.***:32772
访问8000端口。(都可以正常提供服务)
三、用户自定义网络
通过docker network create --driver network_type network_name命令即可创建自定义网络。其中--driver后面支持的类型有三种:bridge、macvlan、overlay
[root@VM_0_6_centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f88b1c490d20 bridge bridge local
0954ad9627bc host host local
7dbe186a84e8 none null local
[root@VM_0_6_centos ~]# ip a
[root@VM_0_6_centos ~]# docker network create --driver bridge my_bridge
326493de5458416e3a1ccbceea5e03760268ae3412c9fe78fe551dadbfc53c95
[root@VM_0_6_centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f88b1c490d20 bridge bridge local
0954ad9627bc host host local
326493de5458 my_bridge bridge local
7dbe186a84e8 none null local
[root@VM_0_6_centos ~]# ip a
通过docker network inspect network_name可以查看该网络的信息
[root@VM_0_6_centos ~]# docker network inspect my_bridge
[
{
"Name": "my_bridge",
"Id": "326493de5458416e3a1ccbceea5e03760268ae3412c9fe78fe551dadbfc53c95",
"Created": "2019-08-06T15:16:08.50367479+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,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
而且通过ip addr可以看到自动在docker主机上创建了一个网卡
[root@VM_0_6_centos ~]# 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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:69:06:60 brd ff:ff:ff:ff:ff:ff
inet 172.16.0.6/20 brd 172.16.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe69:660/64 scope link
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:74:13:f5:ff brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:74ff:fe13:f5ff/64 scope link
valid_lft forever preferred_lft forever
41: vethd9e30c6@if40: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether ca:e9:0a:6d:c6:09 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::c8e9:aff:fe6d:c609/64 scope link
valid_lft forever preferred_lft forever
43: veth2946b2c@if42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 02:65:c5:d4:31:e6 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::65:c5ff:fed4:31e6/64 scope link
valid_lft forever preferred_lft forever
44: br-326493de5458: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state