默认网络
当安装Docker时,会自动创建三个网络。可以使用 docker network ls 命令列出网络
[root@centos-01 ~]# docker network lsNETWORK ID NAME DRIVER SCOPEcdda3ae8795a bridge bridge localed7ffc7437dd host host localfa66bc1a17f4 none null local
四种网络模式
在使用 docker run 创建Docker容器时,可以用 --network 选项指定容器的网络模式,Docker有以下4种网络模式:
--net=host:容器和宿主机共享Network namespace--net=none:容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,配置IP等--net=bridge:默认设置--net=container:name_Or_id:容器和另外一个容器共享Network namespaceBridge
该模式是在启动docker服务后默认的网络模式,当 Docker 启动时,Docker使用Linux桥接(参考《Linux虚拟网络技术》),在宿主机虚拟一个Docker容器网桥**docker0**,Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP
当创建一个 Docker 容器的时候,同时会创建一个 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以接收相同的数据包)。这对接口一端在容器内,即 eth0 ;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间的一个虚拟共享网络。
在安装和启动docker服务之后即可查看到这个 docker0 的虚拟网桥设备
[root@centos-01 ~]# ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:50:75:ae brd ff:ff:ff:ff:ff:ffinet 192.168.126.143/24 brd 192.168.126.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet6 2409:8900:2b86:13cc:a958:4c6e:c162:309d/64 scope global noprefixroute dynamicvalid_lft 3569sec preferred_lft 3569secinet6 fe80::1f3a:afc1:82f6:3f66/64 scope link noprefixroutevalid_lft forever preferred_lft forever3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group defaultlink/ether 02:42:cb:f1:35:ea brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft forever
docker0 网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法通过ip地址直接寻址的,需要通过其他方式来使外部网络可以访问容器,一般会通过访问宿主机ip结合容器的端口(端口映射)进行容器的访问

实现步骤
Docker Daemon利用veth pair技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0和veth1。veth pair技术的特性可以保证无论哪一个veth接收到网络报文,都会将报文传输给另一方Docker Daemon将veth0附加到 Docker Daemon 创建的 docker0网桥上。保证宿主机的网络报文可以发往veth0Docker Daemon将veth1添加到 Docker Container 所属的namespace下,并被改名为eth0。保证宿主机的网络报文若发往veth0则立即会被eth0接收,实现宿主机到Docker Container网络的联通;同时也保证容器单独使用eth0,实现容器网络环境的隔离
缺陷
- 该模式下容器不具有一个
公有IP,就是说和宿主机的eth0不处于同一个网段。导致的结果是在宿主机以外不能直接和容器进行通信 - 虽然
NAT模式经过中间处理实现了这一点,但是NAT模式仍然存在问题与不便,如:容器均需要在宿主机上竞争端口,容器内部服务的访问者需要使用服务发现获知服务的外部端口等 - 另外
NAT模式由于是在三层网络上的实现手段,所以肯定会影响网络传输效率测试
1):查看本机网络 ```bash [root@centos-01 ~]# ip addr 1: lo: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
inet6 ::1/128 scope hostvalid_lft forever preferred_lft forever
valid_lft forever preferred_lft forever
2: ens33:
3: docker0:
**2):创建容器并查看IP**```bash[root@centos-01 ~]# docker run -d --name nginx nginx8afe1080ba992614f96b6868dbbcab463e37c98f8d3fa729245d48c2e6a1e3fe[root@centos-01 ~]# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES8afe1080ba99 nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 80/tcp nginx[root@centos-01 ~]# docker inspect nginx

查看IP发现其ip为 172.17.0.2 ,当容器桥接 docker0 后,会自动分配 ip 地址,之后的IP地址递增
3):查看网桥和端口连接
[root@centos-01 ~]# brctl showbridge name bridge id STP enabled interfacesdocker0 8000.0242cbf135ea no veth3a98010
一个新的网络接口 veth3a98010 被挂到了 docker0 上, veth3a98010 就是新创建容器的虚拟网卡
4):查看 **veth pair** 配置
[root@centos-01 ~]# ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:50:75:ae brd ff:ff:ff:ff:ff:ffinet 192.168.126.143/24 brd 192.168.126.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet6 2409:8900:2b86:13cc:a958:4c6e:c162:309d/64 scope global noprefixroute dynamicvalid_lft 3520sec preferred_lft 3520secinet6 fe80::1f3a:afc1:82f6:3f66/64 scope link noprefixroutevalid_lft forever preferred_lft forever3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultlink/ether 02:42:cb:f1:35:ea brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:cbff:fef1:35ea/64 scope linkvalid_lft forever preferred_lft forever21: veth3a98010@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group defaultlink/ether 16:ea:7d:ca:a3:07 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet6 fe80::14ea:7dff:feca:a307/64 scope linkvalid_lft forever preferred_lft forever[root@centos-01 ~]# brctl showbridge name bridge id STP enabled interfacesdocker0 8000.0242cbf135ea no veth3a98010[root@centos-01 ~]# docker exec -it nginx /bin/bashroot@8afe1080ba99:/# cat /sys/class/net/eth0/iflink21
注:
veth设备是成双成对出现的,一端是容器内部命名为eth0,一端是加入到网桥并命名的vethxxx(通常命名为veth),它们组成了一个数据传输通道,一端进一端出,veth设备连接了两个网络设备并实现了数据通信;在bridge模式下,连在同一网桥上的容器可以相互通信(若出于安全考虑,也可以禁止它们之间通信,方法是在DOCKER_OPTS变量中设置–icc=false,这样只有使用–link才能使两个容器通信)
Host
如果启动容器时使用的是host模式,那么容器将不会获得一个独立的 Network Namespace(网络命名空间) ,而是和宿主机系统共用一个 Network Namespace 。这意味着容器不会虚拟出自己的网卡以及配置自己的ip等,而是使用宿主机的ip以及端口。不过在其他方面例如文件系统、进程列表等还是与之隔离的。使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行 NAT ,host最大的优势就是网络性能比较好,但是已经使用的端口就不能再用了,网络的隔离性不好。
介绍
- host网络模式需要在容器创建时指定
--network=host - host 模式可以直接使用宿主机的IP地址与外界进行通信,若宿主机的
eth0是一个公有 IP,那么容器也拥有这个公有IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行NAT转换 - host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性
缺陷
- 容器网络环境隔离性的弱化。即容器不再拥有隔离、独立的网络栈
- 使用 host 模式的容器虽然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用
- 容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以
bridge网络模式容器的端口映射测试
```shell [root@centos-01 ~]# docker run -d —network=host —name nginx nginx ba0eb1c89ab6b505619db9b6789074db397a9f729ce18aeb82543986971b83d1
[root@centos-01 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ba0eb1c89ab6 nginx “/docker-entrypoint.…” 3 seconds ago Up 2 seconds nginx
注意- 不需要添加 `-p` 参数,因为它使用的就是主机的IP和端口,添加 `-p` 参数后,反而会出现以下警告` WARNING: Published ports are discarded when using host network mode`- 宿主机的ip路由转发功能一定要打开,否则所创建的容器无法联网`echo 1 > /proc/sys/net/ipv4/ip_forward`> host模式端口占用模式是你的容器占用你主机上当前所监听的端口(官网描述为publish)。比如这里nginx占用80端口,那么用host模式启动的时候,主机上的80端口会被nginx占用,这时其他的容器就不能再指定80端口,但可以指定其他端口,所以说一台主机上可以运行多个host模式的容器,只要彼此监听的端口不一样就行```shell[root@centos-01 ~]# curl 192.168.126.143:80<!DOCTYPE html><html><head><title>Welcome to nginx!</title><style>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 andworking. 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>
Container
Container模式 与 Host模式 类似,指定新创建的容器和已经存在的一个容器共享一个 Network Namespace 。新建的容器不会创建自己的网卡等相关操作,而是和与指定的容器共享这些资源。除了网络方面,其文件系统、进程列表等都是隔离的。
注:它并没有改善容器与宿主机以外世界通信的情况(和桥接模式一样,不能连接宿主机以外的其他设备)
[root@centos-01 ~]# docker run -d --name nginx --network=container:ba0eb1c89ab6b50 nginx
None
Docker容器拥有自己的 Network Namespace ,但不会对Docker容器进行任何的网络配置。这表明这个Docker容器没有网卡、IP、路由等信息。需要自己为Docker容器添加网卡、配置IP等。这种方式网络的隔离性最为彻底,即表明关闭了容器的网络功能,也无法访问这个容器。
[root@centos-01 ~]# docker run -d --name nginx --network=none nginx
