Docker新手教程:网络实现的基本原理和参数
Docker网络实现基本使用Linux中的网络命名空间和虚拟网络设备(主要是veth对)。我们建议您在阅读本章之前先熟悉这两部分的基本概念。
基本原理
第一,要实现网络通信,机器至少需要一个网络接口(物理接口或虚拟接口)来发送和接收数据包;另外,如果不同子网之间要进行通信,就需要路由机制。
Docker中的网络接口默认都是虚拟接口。虚拟接口的优点之一是转发效率高。 Linux通过内核中的数据复制来实现虚拟接口之间的数据转发。发送接口的发送缓冲区中的数据包立即复制到接收接口的接收缓冲区中。对于本地系统和容器内的系统来说,它看起来就像一个普通的以太网卡,只不过它不需要实际与外部网络设备通信,而且速度更快。
Docker 容器网络利用了这项技术。它分别在本地主机和容器上创建一个虚拟接口并相互连接(一对这样的接口称为 veth 对)。
创建网络参数
Docker创建容器时,会执行以下操作:
- 创建一对虚拟接口,分别放置在本地主机和新容器上;
- 本地主机端连接默认的docker0或指定的网桥,并有唯一的名称,如veth65f9;
- 将容器的一端放入新容器中,并将其重命名为eth0。该接口仅在容器的命名空间中可见;
- 从桥接器中从可用地址段中获取一个空闲地址分配给容器eth0,并设置默认路由到veth65f9桥接网卡。
完成后,容器可以使用eth0虚拟网卡连接到其他容器和其他网络。
docker运行时可以通过--net参数指定容器的网络配置。有 4 个可选值:
- --net=bridge 这是默认值,连接到默认网桥。
- --net=host 告诉 Docker 不要将容器的网络放入隔离命名空间中,即不要将网络包含在容器内部。此时,容器使用 localhost 网络并具有对 localhost 接口的完全访问权限。与主机上的任何其他根进程一样,容器进程可以打开低范围端口、访问 D-bus 等本地网络服务,并允许容器执行影响整个主机系统的操作,例如重新启动主机。因此,使用此选项时要非常小心。如果再次使用--privileged=true,将允许容器直接管理主机的网络堆栈。
- --net=container:NAME_or_ID 允许 Docker 将新的容器进程插入到现有容器的网络堆栈中。新的容器进程有自己的文件系统、进程列表和资源限制,但与现有容器相同。两个进程共享IP地址和端口等网络资源,可以通过环回接口直接通信。
- --net=none 告诉 Docker 将新容器放到隔离的网络堆栈上,但不管理网络。之后,用户可以自行定制。
网络配置详情
使用--net=none后,用户可以配置自己的网络,使容器拥有和平常一样的访问网络的权限。通过这个过程,你可以了解Docker网络配置的细节。
首先,启动 /bin/bash 容器并指定 --net=none 参数。
$ sudo docker run -i -t --rm --net=none base /bin/bash
root@63f36fc01b5f:/#在本地主机上查找容器进程 ID 并创建网络命名空间。
$ sudo docker inspect -f '{{.State.Pid}}' 63f36fc01b5f
2778
$ pid=2778
$ sudo mkdir -p /var/run/netns
$ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid检查桥网卡的IP和子网掩码信息。
$ ip addr show docker0
21: docker0: ...
inet 172.17.42.1/16 scope global docker0
...创建“vethpair”接口A和B,将A绑定到桥接docker0,并启用
$ sudo ip link add A type veth peer name B
$ sudo brctl addif docker0 A
$ sudo ip link set A up将B放置在容器网络命名空间中,命名为eth0,初始化并设置可用IP(桥接段)和默认网关。
$ sudo ip link set B netns $pid
$ sudo ip netns exec $pid ip link set dev B name eth0
$ sudo ip netns exec $pid ip link set eth0 up
$ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0
$ sudo ip netns exec $pid ip route add default via 172.17.42.1以上是Docker特有的配置网络的流程。
当容器完成后,Docker会删除该容器,容器中的eth0将与网络命名空间一起被丢弃,接口A将自动从docker0中删除。
此外,用户可以使用ip netns exec命令配置指定网络命名空间中的网络来配置容器中的网络。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网