前言

  • 基本原理
  • 创建网络参数
  • 常见的网络模式
  • network
  • null 空网络模式
  • bridge
  • host主机网络模式
  • container 网络模式
  • 总结


docker的网络实现是学习docker的重中之重,首先我们要了解Docker的网络实现其实就是利用了Linux上的网络名字空间和虚拟网络设备(特别是 veth pair)。

基本原理

要实现网络通信,机器需要至少一个网络接口(物理接口或者虚拟接口)来收发数据包;此外,如果不同子网之间要进行通信,需要路由机制。

Docker中的网络接口默认都是虚拟的接口,虚拟接口的优势之一是转发效率较高。Linux通过在内核中进行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据包被直接复制到接收接口的接收缓存中,对于本地系统和容器内系统看来就像是一个正常的以太网卡,只是它不需要真正同外部网络设备通信,速度要很快。

Docker容器网络就利用了这项技术,它在本地主机和容器内分别创建了一个虚拟接口,并让它们彼此连通 (这一对接口就叫做 veth pair)

veth pair

  • 我们发现这个容器带来的网卡 都是成对成对出现的,就是一对的虚拟设备接口,一端连着协议,一端彼此相连。
  • 正因为有这个特性,所以它通常作为桥梁,链接各种虚拟网络设备的。

创建网络参数

Docker创建容器的时候,会执行如下操作

  • 创建一对虚拟接口,分别放到本地主机和新容器中;
  • 本地主机一端桥接到默认的docker 0 或指定网桥上,并且具有一个唯一的名字,如 veth148b541. 执行run成功后,我们可以使用 ifconfig 查看就会发现多了个虚拟网卡
  • 容器一端放到新容器中,并修改名字作为eth0.这个接口只在容器的名字空间可见;
  • 从网桥可用地址段中获取一个空闲地址分配给容器的eth0,并配置默认路由到桥接网卡 veth148b541

完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其它容器和其它网络

docker 容器中GraphDriver docker veth pair_容器

常见的网络模式

network

network 比较典型的网络模式主要有四种,这四种基本满足我们单机容器的所有场景。

null 空网络模式

null 空网络模式:可以帮助我们构建一个没有网络接入的容器环境,以保障数据安全。相当于一个没有联网的计算机。

作用:

  • 保持一个较安全的环境,确保数据不会被他人从网络窃取。可处理一些纯计算任务

格式:
docker run --net=none

使用–net=none 启动容器,并且使用ifconfig查看下容器内的网络配置,可以看到容器内除了 Net Namespace 自带的 lo 网卡外并没有创建任何的虚拟网卡,然后我们再使用 route -n 命令查看一下路由信息:

$ docker run --net=none -it busybox
$ / # 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)
$ / # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

这时看到容器内也并没有配置任何路由信息。

bridge

Docker的bridge网络是启动容器时默认的网络模式;

主要作用

  • 实现容器与容器的互通,可以从一个容器直接通过容器IP访问到另一个容器
  • 实现主机与容器的互通,在容器内启动的业务,可以从主机直接请求。

实现技术

  • Linux veth
    veth 是linux中的虚拟设备接口,veth都是成对出现的,它在容器中,通常充当一个桥梁。veth 可以用来连接虚拟网络设备。例如:veth 可以用来连通两个 Net Namespace,从而使得两个 Net Namespace之间可以互相访问。
  • Linux bridge
    是一个虚拟设备,用来连接网络的设备,相当于物理网络环境中的交换机,linux bridge可以用来转发两个 Net Namespace 内的流量。

自定义网桥命令

$ root@VM-8-11-ubuntu:/home/lighthouse# docker network create my-net
e7fe575b4731606c802e8fb35242aaebad8210e0c0c97870ef7e2fd21bd973dd
$ root@VM-8-11-ubuntu:/home/lighthouse# docker network ls
	NETWORK ID     NAME      DRIVER    SCOPE
	828b93373c17   bridge    bridge    local
	0ab28e475dc6   host      host      local
	e7fe575b4731   my-net    bridge    local   # 上面创建的bridge模式
	e4c628cc77db   none      null      local
$ root@VM-8-11-ubuntu:/home/lighthouse# docker network rm my-net  # 删除命令
	my-net

docker network create 可以指定子网、IP地址范围、网关和其它选项。具体可以执行 docker network create --help 或者 docker network create.

host主机网络模式

host 主机网络模式:可以让容器内的进程共享主机网络,从而监听或修改主机网络。

使用host主机网络模式时

  • libnetwork 不会为容器创建新的网络配置和Net Namespace。
  • Docker 容器中的进程直接共享主机的网络配置,可以直接使用主机的网络信息,此时,在容器内监听的端口,也将直接占用到主机的端口。
  • 除了网络共享主机的网络外,其它的包括进程、文件系统、主机名等都是与主机隔离的。

使用场景:

  • 主机模式网络可用于优化性能,在容器需要处理大量端口的情况下,由于它不需要网络地址转换(NAT),并且也没有为每个端口创建"用户空间代理"
$ root@VM-8-11-ubuntu:~# docker run --name=mynginx --net=host -d nginx
	3553c45f3846a67156e0b35fe698f8b5bb757690923972d9c9e5d65e5005c232
$ root@VM-8-11-ubuntu:~# docker exec -it mynginx cat /etc/hosts
	#
	127.0.1.1 localhost.localdomain VM-8-11-ubuntu
	127.0.0.1 localhost
	
	::1 ip6-localhost ip6-loopback
	fe00::0 ip6-localnet
	ff00::0 ip6-mcastprefix
	ff02::1 ip6-allnodes
	ff02::2 ip6-allrouters
	ff02::3 ip6-allhosts
这时查看容器链路接口,与主机是一致的。而且我们访问端口也是可以访问的了

docker 容器中GraphDriver docker veth pair_运维开发_02

container 网络模式

  • container 网络模式:可以将两个容器放在同一个网络命名空间内,让两个业务通过localhost即可实现访问。
  • 此模式下新创建的容器不会创建自己的网卡,配置自己的Ip,而是和一个指定的容器共享IP、端口范围等。同样的两个容器除了网络方面相同之外,其它的如文件系统,进程列表等都是隔离的。

主要作用:
将两个容器放到同一网络空间中,可以直接通过localhost本地访问

使用命令:
–net container: 已运行的容器名称|ID 或者 --network container:已运行的容器名称| ID

$root@VM-8-11-ubuntu:~# docker run -it --name=mybusy -d busybox 

$root@VM-8-11-ubuntu:~# docker run -it --name=mybusy02 -d --net=container:mybusy busybox
# 查看容器02的ip地址
$root@VM-8-11-ubuntu:~# docker exec -it mybusy02 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
12: eth0@if13: <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 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
       
# 宿主的ip地址       
$root@VM-8-11-ubuntu:~# docker exec -it mybusy 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
12: eth0@if13: <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 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

我们可以发现容器 mybusy02 直接用了 mybusy的网卡信息,这时我们看看暂停宿主容器mybusy

$root@VM-8-11-ubuntu:~# docker stop mybusy
	mybusy
$root@VM-8-11-ubuntu:~# docker exec -it mybusy02 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

这时我们发现mybusy02的容器就只剩下 lo了。当重启mybusy容器后,就又可以获得网卡信息了。

总结

常用网络模式

作用

业务场景

null网络空间模式

不提供任何容器网络

处理一些保密数据,处于安全考虑,需要一个隔离的网络环境执行一些纯计算任务

bridge桥接模式

使得容器和容器之间网络可以互通

容器需要实现网络通信或者提供网络服务

host主机网络模式

让容器内的程序可以使用到主机的网络

容器需要控制主机网络或者用主机网络提供服务

container网络模式

将两个容器放到同一网络空间中,可以直接通过localhost本地访问

两个容器之间需要直接通过localhost通信,一般用于网络接管或者代理外部请求

  • 所有的容器不指定网络的情况下,都是docker 0路由的,docker会给我们的容器分配一个默认的可用IP.
  • docker 常使用的是linux的桥接,宿主机中是一个Docker容器的网桥 docker 0