网络模式
bridge
默认网络,Docker启动后默认创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
host
容器不会获得一个独立的network namespace,而是与宿主机共用一个。
在容器中使用ifconfig查看网络发现显示的是宿主机的网络
none
获取独立的network namespace,但不为容器进行任何网络配置,之后用户可以自己进行配置,容器内部只能使用loopback网络设备,不会再有其他的网络资源。
container
与指定的容器使用同一个network namespace,网卡配置也都是相同的。
自定义
自定义网桥,默认与bridge网络一样。
容器网络模式详解
bridge
Bridge桥接模式的实现步骤主要如下:
- Docker Daemon利用veth pair技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0和veth1。而veth pair技术的特性可以保证无论哪一个veth接收到网络报文,都会将报文传输给另一方。
- Docker Daemon将veth0附加到Docker Daemon创建的docker0网桥上。保证宿主机的网络报文可以发往veth0。
- Docker Daemon将veth1添加到Docker Container所属的namespace下,并被改名为eth0。如此一来,保证宿主机的网络报文若发往veth0,则立即会被eth0接收,实现宿主机到Docker Container网络的联通性;同时,也保证Docker Container单独使用eth0,实现容器网络环境的隔离性。
同时Docker采用NAT(Network Address Translation,网络地址转换)的方式(可自行查询实现原理),让宿主机以外的世界可以主动将网络报文发送至容器内部。
通过Bridger网桥模式实现:
- 容器拥有独立、隔离的网络栈
- 容器和宿主机以外的世界通过NAT建立通信
host
父进程在创建子进程时,如果不使用```CLONE_NEWNET```这个参数标志,那么创建出的子进程会与父 进程共享同一个网络namespace。
Docker就是采用了这个简单的原理,在创建进程启动容器的过程中,没有传入CLONE_NEWNET
参数标志,实现Docker Container与宿主机共享同一个网络环境,即实现host网络模式。
优势:
- 可以直接使用宿主机的IP地址与外界进行通信,若宿主机的eth0是一个公有IP,那么容器也拥有这个公有IP。
- 同时容器内服务的端口也可以使用宿主机的端口,无需额外进行NAT转换。
缺陷:
- 最明显的是Docker Container网络环境隔离性的弱化,即容器不再拥有隔离、独立的网络栈。
- 使用host模式的Docker Container虽然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用;
- 容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以bridge网络模式容器的端口映射。
container
Docker Container的container网络模式在实现过程中,不涉及网桥,同样也不需要创建虚拟网卡veth pair。
完成container网络模式的创建只需要两个步骤:
- 查找container(即需要被共享网络环境的容器)的网络namespace;
- 将新创建的Docker Container(也是需要共享其他网络的容器)的namespace,使用container的namespace
优势:
- 在这种模式下的Docker Container可以通过localhost来访问namespace下的其他容器,传输效率较高。
- 虽然多个容器共享网络环境,但是多个容器形成的整体依然与宿主机以及其他容器形成网络隔离。
- 这种模式还节约了一定数量的网络资源。
缺陷:
- 没有改善容器与宿主机以外世界通信的情况。
容器网络访问原理
Linux IP信息包过滤原理
Docker主要通过netfilter/iptables实现网络通信。
iptables由netfilter和iptables组成,netfilter组件是Linux内核集成的信息包过滤系统,它维护一个信息包过滤表,这个表用于控制信息包过滤处理的规则集。而iptables只是一个在用户空间的工具,用于增删改查这个过滤表的规则。
容器访问外部
容器将数据报发送给容器网关,即docker0虚拟网桥,然后虚拟网桥再转发到实际的网卡并由实际网卡转发到物理网关,然后向目标进行层层转发直到抵达目标地址。
外部访问容器
容器通过将服务的实际端口在宿主机上进行端口映射,外部客户端通过连接宿主机的映射端口来访问容器内的服务。